From e50c63dca2553dd3e78a34d7af7491e69d298b10 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 22 Sep 2017 23:23:34 +0300 Subject: [PATCH 001/291] updated version to 1.0 --- dist/app.js | 30 +++++++++++++------------- src/global/Config.js | 2 +- src/manager/Manager.js | 2 +- src/manager/plugins/Backup.js | 2 +- src/manager/plugins/Config.js | 2 +- src/manager/plugins/Energy.js | 2 +- src/manager/plugins/Mutator.js | 2 +- src/manager/plugins/OrganismsDos.js | 2 +- src/manager/plugins/OrganismsGarmin.js | 2 +- src/manager/plugins/Status.js | 2 +- src/organism/JSVM.js | 2 +- src/organism/OperatorsDos.js | 2 +- src/organism/OperatorsGarmin.js | 2 +- src/organism/OrganismDos.js | 2 +- src/organism/OrganismGarmin.js | 2 +- src/visual/Canvas.js | 2 +- src/visual/World.js | 2 +- 17 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dist/app.js b/dist/app.js index e713d79..f59c9f1 100644 --- a/dist/app.js +++ b/dist/app.js @@ -1651,7 +1651,7 @@ class Observer { class OrganismDos extends __WEBPACK_IMPORTED_MODULE_0__organism_base_Organism__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } onRun() { @@ -1998,7 +1998,7 @@ const MAX_STACK_SIZE = 30000; class JSVM extends __WEBPACK_IMPORTED_MODULE_2__global_Observer__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } /** @@ -2593,7 +2593,7 @@ class Manager extends __WEBPACK_IMPORTED_MODULE_1__global_Observer__["a" /* defa version() { let plugins = this._plugins; let ver = '' + - 'Manager : 0.9\n' + + 'Manager : 1.0\n' + ' World : ' + __WEBPACK_IMPORTED_MODULE_4__visual_World__["a" /* default */].version() + '\n' + ' Canvas : ' + __WEBPACK_IMPORTED_MODULE_5__visual_Canvas__["a" /* default */].version() + '\n'; @@ -2877,7 +2877,7 @@ class Queue { class Backup { static version() { - return '0.1'; + return '1.0'; } constructor(orgs, world, positions) { @@ -2973,7 +2973,7 @@ class Backup { class Config { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -3003,7 +3003,7 @@ class Config { class Energy { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -3100,7 +3100,7 @@ const MAX_VAR = __WEBPACK_IMPORTED_MODULE_4__organism_Num__["a" /* default class Mutator { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -3247,7 +3247,7 @@ const ORGANISM = 2; class OrganismsDos extends __WEBPACK_IMPORTED_MODULE_0__manager_plugins_base_Organisms__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -3408,7 +3408,7 @@ class OrganismsDos extends __WEBPACK_IMPORTED_MODULE_0__manager_plugins_base_Org class OrganismsGarmin extends __WEBPACK_IMPORTED_MODULE_4__manager_plugins_base_Organisms__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -3483,7 +3483,7 @@ const PERIOD = 10000; class Status { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { @@ -6048,7 +6048,7 @@ const CONDITION_BITS = 2; class OperatorsDos extends __WEBPACK_IMPORTED_MODULE_3__base_Operators__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } constructor(offs, vars, obs) { @@ -6345,7 +6345,7 @@ const CONDITION_BITS = 2; class OperatorsGarmin extends __WEBPACK_IMPORTED_MODULE_2__base_Operators__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } constructor(offs, vars, obs) { @@ -6506,7 +6506,7 @@ class OperatorsGarmin extends __WEBPACK_IMPORTED_MODULE_2__base_Operators__["a" class OrganismGarmin extends __WEBPACK_IMPORTED_MODULE_0__organism_base_Organism__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } /** @@ -6571,7 +6571,7 @@ class OrganismGarmin extends __WEBPACK_IMPORTED_MODULE_0__organism_base_Organism */ class Canvas { static version () { - return '0.1'; + return '1.0'; } constructor(width, height) { @@ -6719,7 +6719,7 @@ const FREE_DOT_ATTEMPTS = 300; class World extends __WEBPACK_IMPORTED_MODULE_0__global_Observer__["a" /* default */] { static version() { - return '0.1'; + return '1.0'; } constructor (width, height) { diff --git a/src/global/Config.js b/src/global/Config.js index 29c5caa..dc7a249 100644 --- a/src/global/Config.js +++ b/src/global/Config.js @@ -149,7 +149,7 @@ const Config = { * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. */ - codeBitsPerVar: 2, + codeBitsPerVar: 3, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is diff --git a/src/manager/Manager.js b/src/manager/Manager.js index 5ba51c2..28210be 100644 --- a/src/manager/Manager.js +++ b/src/manager/Manager.js @@ -101,7 +101,7 @@ export default class Manager extends Observer { version() { let plugins = this._plugins; let ver = '' + - 'Manager : 0.9\n' + + 'Manager : 1.0\n' + ' World : ' + World.version() + '\n' + ' Canvas : ' + Canvas.version() + '\n'; diff --git a/src/manager/plugins/Backup.js b/src/manager/plugins/Backup.js index 778db84..5238339 100644 --- a/src/manager/plugins/Backup.js +++ b/src/manager/plugins/Backup.js @@ -12,7 +12,7 @@ import Console from './../../global/Console'; export default class Backup { static version() { - return '0.1'; + return '1.0'; } constructor(orgs, world, positions) { diff --git a/src/manager/plugins/Config.js b/src/manager/plugins/Config.js index b4e7b31..64d84cd 100644 --- a/src/manager/plugins/Config.js +++ b/src/manager/plugins/Config.js @@ -7,7 +7,7 @@ import {api} from './../../global/Config'; export default class Config { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/manager/plugins/Energy.js b/src/manager/plugins/Energy.js index 360ee86..2086f0b 100644 --- a/src/manager/plugins/Energy.js +++ b/src/manager/plugins/Energy.js @@ -9,7 +9,7 @@ import Console from './../../global/Console'; export default class Energy { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/manager/plugins/Mutator.js b/src/manager/plugins/Mutator.js index ee139ec..a6fc7e3 100644 --- a/src/manager/plugins/Mutator.js +++ b/src/manager/plugins/Mutator.js @@ -21,7 +21,7 @@ const MAX_VAR = Num.MAX_VAR; export default class Mutator { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/manager/plugins/OrganismsDos.js b/src/manager/plugins/OrganismsDos.js index 1585139..fdc3f91 100644 --- a/src/manager/plugins/OrganismsDos.js +++ b/src/manager/plugins/OrganismsDos.js @@ -21,7 +21,7 @@ const ORGANISM = 2; export default class OrganismsDos extends Organisms { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/manager/plugins/OrganismsGarmin.js b/src/manager/plugins/OrganismsGarmin.js index 75e1c61..8181fe7 100644 --- a/src/manager/plugins/OrganismsGarmin.js +++ b/src/manager/plugins/OrganismsGarmin.js @@ -18,7 +18,7 @@ import Organisms from './../../manager/plugins/base/Organisms'; export default class OrganismsGarmin extends Organisms { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/manager/plugins/Status.js b/src/manager/plugins/Status.js index e8ec3f1..c46aa74 100644 --- a/src/manager/plugins/Status.js +++ b/src/manager/plugins/Status.js @@ -12,7 +12,7 @@ const PERIOD = 10000; export default class Status { static version() { - return '0.1'; + return '1.0'; } constructor(manager) { diff --git a/src/organism/JSVM.js b/src/organism/JSVM.js index aafe50d..54cb832 100644 --- a/src/organism/JSVM.js +++ b/src/organism/JSVM.js @@ -21,7 +21,7 @@ const MAX_STACK_SIZE = 30000; export default class JSVM extends Observer { static version() { - return '0.1'; + return '1.0'; } /** diff --git a/src/organism/OperatorsDos.js b/src/organism/OperatorsDos.js index f8338b4..7a301b1 100644 --- a/src/organism/OperatorsDos.js +++ b/src/organism/OperatorsDos.js @@ -28,7 +28,7 @@ const CONDITION_BITS = 2; export default class OperatorsDos extends Operators { static version() { - return '0.1'; + return '1.0'; } constructor(offs, vars, obs) { diff --git a/src/organism/OperatorsGarmin.js b/src/organism/OperatorsGarmin.js index c4870b8..5b116e2 100644 --- a/src/organism/OperatorsGarmin.js +++ b/src/organism/OperatorsGarmin.js @@ -25,7 +25,7 @@ const CONDITION_BITS = 2; export default class OperatorsGarmin extends Operators { static version() { - return '0.1'; + return '1.0'; } constructor(offs, vars, obs) { diff --git a/src/organism/OrganismDos.js b/src/organism/OrganismDos.js index eda5f9e..5d17460 100644 --- a/src/organism/OrganismDos.js +++ b/src/organism/OrganismDos.js @@ -8,7 +8,7 @@ import Organism from './../organism/base/Organism'; export default class OrganismDos extends Organism { static version() { - return '0.1'; + return '1.0'; } onRun() { diff --git a/src/organism/OrganismGarmin.js b/src/organism/OrganismGarmin.js index 8452756..f265d71 100644 --- a/src/organism/OrganismGarmin.js +++ b/src/organism/OrganismGarmin.js @@ -10,7 +10,7 @@ import {EVENTS} from './../global/Events'; export default class OrganismGarmin extends Organism { static version() { - return '0.1'; + return '1.0'; } /** diff --git a/src/visual/Canvas.js b/src/visual/Canvas.js index f1def6b..66695e5 100644 --- a/src/visual/Canvas.js +++ b/src/visual/Canvas.js @@ -5,7 +5,7 @@ */ export default class Canvas { static version () { - return '0.1'; + return '1.0'; } constructor(width, height) { diff --git a/src/visual/World.js b/src/visual/World.js index e47208b..39d93e2 100644 --- a/src/visual/World.js +++ b/src/visual/World.js @@ -30,7 +30,7 @@ const FREE_DOT_ATTEMPTS = 300; export default class World extends Observer { static version() { - return '0.1'; + return '1.0'; } constructor (width, height) { From 6bd11b4c458657057b236623cba9e396a67b3c7f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 22 Sep 2017 23:27:38 +0300 Subject: [PATCH 002/291] fixed tests... --- src/global/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/global/Config.js b/src/global/Config.js index dc7a249..29c5caa 100644 --- a/src/global/Config.js +++ b/src/global/Config.js @@ -149,7 +149,7 @@ const Config = { * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. */ - codeBitsPerVar: 3, + codeBitsPerVar: 2, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is From 5c9830fdd0ba27ffe91b8d57c25661cf754cb437 Mon Sep 17 00:00:00 2001 From: Alex Mekhovov Date: Tue, 26 Sep 2017 16:33:30 +0200 Subject: [PATCH 003/291] Fix path to webpack looks like folder should be `.bin` instead of `bin` :) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b54ba44..03388db 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ jevo.js is a native JavaScript/ES6 based, digital organisms evolution simulator. - Clone this repo to your local machine - Go to the root folder of cloned repo - Run `install.bat` under Windows or `npm install` on other platforms -- Run `build.bat` under Windows or `./node_modules/bin/webpack` on other platforms +- Run `build.bat` under Windows or `./node_modules/.bin/webpack` on other platforms - Run `./dist/index.html` under chrome browser enjoy out team! From 31c74ec4c7f67bd9d8ea3d318477f06049cd11ab Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 01:09:08 +0200 Subject: [PATCH 004/291] update of project name to 'construct' --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0ba881..9aae1a6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # construct -[![Build Status](https://travis-ci.org/tmptrash/jevo.js.svg?branch=master)](https://travis-ci.org/tmptrash/jevo.js) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/9bd160adb2da4ea08ff64ea8c4dbe14e)](https://www.codacy.com/app/tmptrash/jevo.js?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/jevo.js&utm_campaign=Badge_Grade) +[![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs ([digital organisms](https://en.wikipedia.org/wiki/Digital_organism)). This project similar to [Avida](https://en.wikipedia.org/wiki/Avida), but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and [distributed computing](https://en.wikipedia.org/wiki/Distributed_computing) to speed up the calculations. Generally, it consists of [servers](https://github.com/tmptrash/jevo.js/tree/v0.2/server/src), which just a proxy between [clients](https://github.com/tmptrash/jevo.js/tree/v0.2/client/src). All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run `index.html` (just drop it into the browser) in Chrome without server. From cde57fc17e44f94b22c859c9d4988d6f001f5e96 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 01:21:50 +0200 Subject: [PATCH 005/291] fixes related to codacy issues --- client/src/jsvm/JSVMSpec.js | 62 +++++++++---------- .../plugins/organisms/dos/OrganismSpec.js | 26 ++++---- common/tests/Helper.js | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/client/src/jsvm/JSVMSpec.js b/client/src/jsvm/JSVMSpec.js index c083c97..2c23a5e 100644 --- a/client/src/jsvm/JSVMSpec.js +++ b/client/src/jsvm/JSVMSpec.js @@ -13,7 +13,7 @@ describe("client/src/organism/JSVM", () => { it("Checking jsvm creation", () => { let flag = false; const obs = new Observer(1); - const jsvm = new JSVM(() => flag = true, obs, ()=>{}); + const jsvm = new JSVM(() => flag = true, obs, () => {}); jsvm.run(); expect(flag).toEqual(false); @@ -23,10 +23,10 @@ describe("client/src/organism/JSVM", () => { it("Checking parent argument and 'cloning' mode", () => { const obs = new Observer(1); - const parent = new JSVM(()=>{}, obs, ()=>{}); + const parent = new JSVM(() => {}, obs, () => {}); parent.insertLine(); - const jsvm = new JSVM(()=>{}, obs, ()=>{}, parent); + const jsvm = new JSVM(() => {}, obs, () => {}, parent); expect(jsvm.code[0] === parent.code[0]).toEqual(true); expect(jsvm.size === parent.size).toEqual(true); @@ -38,7 +38,7 @@ describe("client/src/organism/JSVM", () => { it("Checking 'vars' getter for non 'cloning' mode", () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); expect(jsvm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); @@ -47,7 +47,7 @@ describe("client/src/organism/JSVM", () => { it("Checking no code size", () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); expect(jsvm.size).toEqual(0); jsvm.run(); @@ -58,7 +58,7 @@ describe("client/src/organism/JSVM", () => { it("Checking destroy", () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); jsvm.destroy(); expect(jsvm.code).toEqual(null); @@ -66,7 +66,7 @@ describe("client/src/organism/JSVM", () => { it("Checking 'code' and 'size' properties", () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); expect(jsvm.code instanceof Array).toEqual(true); expect(jsvm.size).toEqual(0); @@ -87,7 +87,7 @@ describe("client/src/organism/JSVM", () => { it("Checking 'operators' property", () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, Operators); + const jsvm = new JSVM(() => {}, obs, Operators); expect(jsvm.operators instanceof Operators).toEqual(true); @@ -101,7 +101,7 @@ describe("client/src/organism/JSVM", () => { // get size () {return 1} // } // const obs = new Observer(1); - // const jsvm = new JSVM(()=>{}, obs, ()=>{}); + // const jsvm = new JSVM(() => {}, obs, () => {}); // const coc = api.get('codeOperatorsCls'); // const yp = api.get('codeYieldPeriod'); // const fc = api.get('codeFitnessCls'); @@ -123,8 +123,8 @@ describe("client/src/organism/JSVM", () => { it("Checking crossover with increasing child code", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -164,8 +164,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with decreasing child code", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -203,8 +203,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with the same child code size", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -243,8 +243,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size in parents", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); jsvm1.crossover(jsvm2); expect(jsvm1.size).toEqual(0); @@ -255,8 +255,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size for one parent and twp lines of code for other", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -285,8 +285,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(()=>{}, obs, ()=>{}); - const jsvm2 = new JSVM(()=>{}, obs, ()=>{}); + const jsvm1 = new JSVM(() => {}, obs, () => {}); + const jsvm2 = new JSVM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -317,7 +317,7 @@ describe("client/src/organism/JSVM", () => { it('Checking insertLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); expect(jsvm.size).toEqual(0); jsvm.insertLine(); @@ -329,7 +329,7 @@ describe("client/src/organism/JSVM", () => { }); it('Checking insertLine() method 2', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; @@ -345,7 +345,7 @@ describe("client/src/organism/JSVM", () => { it('Checking copyLines() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -376,7 +376,7 @@ describe("client/src/organism/JSVM", () => { }); it('Checking copyLines() method 2', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -407,7 +407,7 @@ describe("client/src/organism/JSVM", () => { }); it('Checking copyLines() method 3', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -438,7 +438,7 @@ describe("client/src/organism/JSVM", () => { }); it('Checking copyLines() method with no code', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let rand = Helper.rand; Helper.rand = () => 0; @@ -452,7 +452,7 @@ describe("client/src/organism/JSVM", () => { it('Checking updateLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; @@ -471,7 +471,7 @@ describe("client/src/organism/JSVM", () => { it('Checking removeLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); jsvm.insertLine(); expect(jsvm.size).toEqual(1); @@ -482,7 +482,7 @@ describe("client/src/organism/JSVM", () => { }); it('Checking removeLine() for empty code', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); expect(jsvm.size).toEqual(0); jsvm.removeLine(); @@ -495,7 +495,7 @@ describe("client/src/organism/JSVM", () => { it('Checking getLine()', () => { const obs = new Observer(2); - const jsvm = new JSVM(()=>{}, obs, ()=>{}); + const jsvm = new JSVM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 9e0c848..a971c73 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -10,7 +10,7 @@ describe("client/src/organism/OrganismDos", () => { let cls; it("Checking organism creation", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); expect(org.id).toEqual(0); expect(org.x).toEqual(1); @@ -32,7 +32,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking organism creation from parent", () => { - const parent = new OrganismDos(1, 3, 4, true, null, ()=>{}); + const parent = new OrganismDos(1, 3, 4, true, null, () => {}); parent.jsvm.insertLine(); parent.energy = 123; parent.changes = 0xaabbcc; @@ -43,7 +43,7 @@ describe("client/src/organism/OrganismDos", () => { parent.cloneEnergyPercent = 0.34; parent._mem = [1,2,4,3]; - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}, parent); + let org = new OrganismDos(0, 1, 2, true, null, () => {}, parent); expect(org.jsvm.code[0] === parent.jsvm.code[0]).toEqual(true); expect(org.jsvm.size === parent.jsvm.size).toEqual(true); @@ -62,7 +62,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking organism coordinates", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); org.x = 4; org.y = 5; @@ -78,7 +78,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking if organism if alive", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; const speriod = OConfig.orgEnergySpendPeriod; @@ -100,7 +100,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking organism changes", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); expect(org.changes).toEqual(1); org.changes = 10; @@ -112,7 +112,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking run() method", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); expect(org.iterations).toEqual(0); org.run(); @@ -125,7 +125,7 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of age", () => { const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); OConfig.orgAlivePeriod = 30000; for (let i = 0; i < OConfig.orgAlivePeriod; i++) { @@ -140,7 +140,7 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of zero energy", () => { const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); OConfig.orgAlivePeriod = 30000; expect(org.energy).toEqual(OConfig.orgStartEnergy); @@ -155,7 +155,7 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of grab energy", () => { const period = OConfig.orgEnergySpendPeriod; - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); OConfig.orgEnergySpendPeriod = 1; org.energy = 1; @@ -170,7 +170,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking grabbing energy", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); const energy = org.energy; org.grabEnergy(10); @@ -180,7 +180,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking organism color change", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); const color = org.color; org.changes = 10; @@ -190,7 +190,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking destroy() method", () => { - let org = new OrganismDos(0, 1, 2, true, null, ()=>{}); + let org = new OrganismDos(0, 1, 2, true, null, () => {}); expect(org.alive).toEqual(true); expect(org.energy > 0).toEqual(true); diff --git a/common/tests/Helper.js b/common/tests/Helper.js index aad1cd2..96cfd56 100644 --- a/common/tests/Helper.js +++ b/common/tests/Helper.js @@ -53,7 +53,7 @@ class Helper { const eventCb = () => waitObj.done = true; const waitCb = () => {obj.off(event, eventCb); cb(); return true}; - !cb && (cb = preCb) && (preCb = ()=>{}); + !cb && (cb = preCb) && (preCb = () => {}); obj.on(event, eventCb); preCb(); From 336c2655742c0bf53c7d7c64e43655d29977f89a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 10:20:50 +0200 Subject: [PATCH 006/291] fixed issue found by codacy service fixed unused variables --- client/src/manager/plugins/Status.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/client/src/manager/plugins/Status.js b/client/src/manager/plugins/Status.js index 0a2305b..0353fd4 100644 --- a/client/src/manager/plugins/Status.js +++ b/client/src/manager/plugins/Status.js @@ -19,8 +19,6 @@ class Status { this._energy = 0; this._codeSize = 0; this._runLines = 1; - this._changes = 0; - this._fitness = 0; this._times = 0; this._oldValues = [0, 0, 0]; this._speed = [0, 0, 0]; @@ -36,16 +34,16 @@ class Status { if (stamp - this._stamp < PERIOD) {return} const times = this._times || 1; - const times_1 = (times - 1) || 1; + const times1 = (times - 1) || 1; const realIps = this._ips / times; const orgAmount = orgs.size || 1; const sips = `ips:${realIps.toFixed(realIps < 10 ? 2 : 0)}`.padEnd(10); const slps = this._format(this._runLines / times, 'lps', orgAmount, 0, 14, 1, false, false); const sorgs = this._format(orgAmount, 'org', orgAmount, 0, 10, 1, false, false); const senergy = this._format(this._energy / times, 'nrg', orgAmount, 0, 14, 1, false); - const siq = this._format(this._speed[0] / times_1, 'iq', orgAmount, 3, 13, 1000); - const schanges = this._format(this._speed[1] / times_1, 'che', orgAmount, 3, 12, 100000); - const sfit = this._format(this._speed[2] / times_1, 'fit', orgAmount, 3, 14); + const siq = this._format(this._speed[0] / times1, 'iq', orgAmount, 3, 13, 1000); + const schanges = this._format(this._speed[1] / times1, 'che', orgAmount, 3, 12, 100000); + const sfit = this._format(this._speed[2] / times1, 'fit', orgAmount, 3, 14); const scode = this._format(this._codeSize / times, 'cod', orgAmount, 1, 12, 1, false); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); @@ -89,8 +87,6 @@ class Status { this._ips += ips; this._energy += energy; this._codeSize += codeSize; - this._changes += changes; - this._fitness += fitness; this._setOldValues(energy, changes, fitness); this._times++; @@ -100,8 +96,6 @@ class Status { this._ips = 0; this._energy = 0; this._codeSize = 0; - this._changes = 0; - this._fitness = 0; this._runLines = 0; this._times = 0; this._stamp = stamp; From 9c16666087dca98c14e8bd587a5cb5db881e3dcc Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 16:59:23 +0200 Subject: [PATCH 007/291] updated README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9aae1a6..baf0b2f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ # construct [![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) -construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs ([digital organisms](https://en.wikipedia.org/wiki/Digital_organism)). This project similar to [Avida](https://en.wikipedia.org/wiki/Avida), but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and [distributed computing](https://en.wikipedia.org/wiki/Distributed_computing) to speed up the calculations. Generally, it consists of [servers](https://github.com/tmptrash/jevo.js/tree/v0.2/server/src), which just a proxy between [clients](https://github.com/tmptrash/jevo.js/tree/v0.2/client/src). All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run `index.html` (just drop it into the browser) in Chrome without server. - -More details on [blog](https://jevosite.wordpress.com) and youtube [channel](https://www.youtube.com/playlist?list=PL1NiKjXMaBimPuybPIXkVuO1MYy53XcdW). Video presentation in russian is [here](https://www.youtube.com/watch?v=9ykr9KzcKq8). +

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxy between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run `index.html` (just drop it into the browser) in Chrome without server. More details on blog and youtube channel. Video presentation in russian is here. +

# Requirements - Last version of Chrome browser From f78b971fa2ebda7c3cc1d36a0147a90204581eff Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 17:50:44 +0200 Subject: [PATCH 008/291] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index baf0b2f..3766182 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # construct [![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) -

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxy between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run `index.html` (just drop it into the browser) in Chrome without server. More details on blog and youtube channel. Video presentation in russian is here. +

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxy between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details on blog and youtube channel. Video presentation in russian is here.

# Requirements From be48566665f44c2ea31d0c8f9079056d3866e95d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 17:57:24 +0200 Subject: [PATCH 009/291] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3766182..78751c7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # construct [![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) -

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxy between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details on blog and youtube channel. Video presentation in russian is here. +

`construct` is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxies between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details for russian speaking people on blog and youtube channel. See video presentation here.

# Requirements From cec93e497776f7eb01506e6cd37d06fdd6c64280 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 18:04:15 +0200 Subject: [PATCH 010/291] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 78751c7..00aae1e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # construct [![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) -

`construct` is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxies between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details for russian speaking people on blog and youtube channel. See video presentation here. +

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxies between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details for russian speaking people on blog and youtube channel. See video presentation here.

# Requirements From 1e4733f7963001bc0050034d90d691315452ced2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 18:10:15 +0200 Subject: [PATCH 011/291] updated README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00aae1e..216ae21 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # construct [![Build Status](https://travis-ci.org/tmptrash/construct.svg?branch=master)](https://travis-ci.org/tmptrash/construct) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/da2d5c5f53d04df79c9aae3599555b4e)](https://www.codacy.com/app/flatline/construct?utm_source=github.com&utm_medium=referral&utm_content=tmptrash/construct&utm_campaign=Badge_Grade) -

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxies between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details for russian speaking people on blog and youtube channel. See video presentation here. +

construct is a native JavaScript/ES6 based, digital organisms evolution simulator. It's used for study the evolutionary biology of self-replicating and evolving computer programs (digital organisms). This project similar to Avida, but works with more abstract language (Digital Organism Script - DOS) instead of assembler. It uses special DOSVM for running DOS byte code and distributed computing to speed up the calculations. Generally, it consists of servers, which just a proxies between clients. All calculations are made on a client side only. It's possible to run the system in a "serverless" mode. For this, you have to run index.html (just drop it into the browser) in Chrome without server. More details for russian speaking people on blog and youtube channel. See video presentation here.

# Requirements @@ -29,4 +29,4 @@ Note: to improve speed, type `man.api.visualize(false)` in Chrome's devtool console during application run ___ -P.S. If you `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! \ No newline at end of file +P.S. If you `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! \ No newline at end of file From 7e76bb97f21d70684c5f8143284263f1b0f92cb0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 18:29:48 +0200 Subject: [PATCH 012/291] fixed #80 --- server/src/share/Console.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/server/src/share/Console.js b/server/src/share/Console.js index 7ae574b..9a0de92 100644 --- a/server/src/share/Console.js +++ b/server/src/share/Console.js @@ -4,9 +4,14 @@ * @author flatline */ class Console { - static error(...msg) {console.log('\x1b[31m%s\x1b[0m', msg.join(''))} - static warn (...msg) {console.log('\x1b[33m%s\x1b[0m', msg.join(''))} - static info (...msg) {console.log('\x1b[37m%s\x1b[0m', msg.join(''))} + static error(...msg) {console.log(this._time() + '\x1b[31m%s\x1b[0m', msg.join(''))} + static warn (...msg) {console.log(this._time() + '\x1b[33m%s\x1b[0m', msg.join(''))} + static info (...msg) {console.log(this._time() + '\x1b[37m%s\x1b[0m', msg.join(''))} + static _time() { + const date = new Date; + + return `${date.toLocaleDateString()} ${date.toLocaleTimeString()} `; + } } module.exports = Console; \ No newline at end of file From e70452cb220316eb2579079a671cd06199cbe01d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 6 Dec 2017 23:25:57 +0200 Subject: [PATCH 013/291] Closed #80 --- server/src/server/Server.js | 2 +- server/src/share/Console.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/server/Server.js b/server/src/server/Server.js index 8a4e162..f5b2eb1 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -222,7 +222,7 @@ class Server extends Connection { sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); - Console.warn(`Server: client ${clientId} has disconnected by reason: ${this.closeReason}`); + Console.warn(`Client ${clientId} has disconnected by reason: ${this.closeReason}`); } } diff --git a/server/src/share/Console.js b/server/src/share/Console.js index 9a0de92..b4776d1 100644 --- a/server/src/share/Console.js +++ b/server/src/share/Console.js @@ -4,13 +4,13 @@ * @author flatline */ class Console { - static error(...msg) {console.log(this._time() + '\x1b[31m%s\x1b[0m', msg.join(''))} - static warn (...msg) {console.log(this._time() + '\x1b[33m%s\x1b[0m', msg.join(''))} - static info (...msg) {console.log(this._time() + '\x1b[37m%s\x1b[0m', msg.join(''))} + static error(...msg) {console.log('%s \x1b[31m%s\x1b[0m', this._time(), msg.join(''))} + static warn (...msg) {console.log('%s \x1b[33m%s\x1b[0m', this._time(), msg.join(''))} + static info (...msg) {console.log('%s \x1b[32m%s\x1b[0m', this._time(), msg.join(''))} static _time() { const date = new Date; - return `${date.toLocaleDateString()} ${date.toLocaleTimeString()} `; + return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; } } From fe61bf2964d1d258d48df178e3a19e268c352c10 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 7 Dec 2017 00:15:04 +0200 Subject: [PATCH 014/291] Closed #81 --- .../src/manager/plugins/organisms/Config.js | 12 +++++----- .../src/manager/plugins/organisms/Mutator.js | 4 +--- .../src/manager/plugins/organisms/Organism.js | 2 +- .../plugins/organisms/dos/Code2String.js | 8 +++---- .../plugins/organisms/dos/Operators.js | 10 ++++---- .../plugins/organisms/garmin/Code2String.js | 10 ++++---- .../plugins/organisms/garmin/Operators.js | 10 ++++---- client/src/{jsvm => vm}/Num.js | 0 client/src/{jsvm => vm}/NumSpec.js | 0 client/src/{jsvm => vm}/Operators.js | 0 client/src/{jsvm/JSVM.js => vm/VM.js} | 24 +++++++++---------- client/src/{jsvm/JSVMSpec.js => vm/VMSpec.js} | 12 +++++----- 12 files changed, 44 insertions(+), 48 deletions(-) rename client/src/{jsvm => vm}/Num.js (100%) rename client/src/{jsvm => vm}/NumSpec.js (100%) rename client/src/{jsvm => vm}/Operators.js (100%) rename client/src/{jsvm/JSVM.js => vm/VM.js} (93%) rename client/src/{jsvm/JSVMSpec.js => vm/VMSpec.js} (98%) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 7b5fb92..17c8ab5 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -20,13 +20,13 @@ const Config = { ORG_MAX_COLOR: Number.MAX_SAFE_INTEGER, /** * {Array} Probabilities which used, when mutator decides what to do: - * add, change, delete code line inside the jsvm; change amount of + * add, change, delete code line inside the vm; change amount of * mutations or change mutations period... Depending on these * values, organism may have different strategies of living. * For example: if add value is bigger then del and change, - * then jsvm size will be grow up all the time. If del value is + * then vm size will be grow up all the time. If del value is * bigger then other, then it will be decreased to zero lines - * of jsvm and organism will die. + * of vm and organism will die. * Format: [ * add - Probability of adding new line to the code * change - Probability of changing existing line of code @@ -47,7 +47,7 @@ const Config = { */ orgMutationProbsMaxValue: 100, /** - * {Number} Percent of mutations from jsvm size, which will be applied to + * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ orgCloneMutationPercent: 0.01, @@ -77,7 +77,7 @@ const Config = { orgStartAmount: 100, /** * {Number} Amount of energy for first organisms. They are like Adam and - * Eve. It means that these empty (without jsvm) organism were created + * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ orgStartEnergy: 10000, @@ -129,7 +129,7 @@ const Config = { */ orgMaxOrgs: 300, /** - * {Number} If organism reach this limit of amount of jsvm lines, then codeSizeCoef + * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, * because our CPU's are slow and organisms with big codes are very slow. But * it's possible for organisms to go outside the limit by inventing new diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index c447f37..e251130 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -10,11 +10,9 @@ * @author flatline */ const EVENTS = require('./../../../share/Events').EVENTS; -const Config = require('./../../../share/Config').Config; const OConfig = require('./../../../manager/plugins/organisms/Config'); const Helper = require('./../../../../../common/src/Helper'); -const Organism = require('./dos/Organism'); -const Num = require('./../../../jsvm/Num'); +const Num = require('./../../../vm/Num'); const VAR_BITS_OFFS = Num.VAR_BITS_OFFS - 1; const VARS = Num.VARS; diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 590f828..5e5217e 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -11,7 +11,7 @@ const Config = require('./../../../share/Config').Config; const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENTS = require('./../../../share/Events').EVENTS; const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; -const JSVM = require('./../../../jsvm/JSVM'); +const JSVM = require('./../../../vm/VM'); const IS_NUM = Helper.isNumeric; diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 5e34bf6..b8c109d 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -5,7 +5,7 @@ * * @author flatline */ -const Num = require('./../../../../jsvm/Num'); +const Num = require('./../../../../vm/Num'); /** * {Function} Just a shortcuts @@ -22,7 +22,7 @@ class Code2String { this._manager = manager; /** * {Object} These operator handlers should return string representation - * of numeric based byte jsvm. + * of numeric based byte vm. */ this._OPERATORS_CB = { 0 : this._onVar.bind(this), @@ -127,8 +127,8 @@ class Code2String { * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) * BITS_PER_VAR bits - variable index or all bits till the end for constant * - * @param {Num} num Packed into number jsvm line - * @return {String} Parsed jsvm line string + * @param {Num} num Packed into number vm line + * @return {String} Parsed vm line string */ _onVar(num) { const var1 = VAR1(num); diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 9589f18..da4e6ce 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -11,8 +11,8 @@ const Helper = require('./../../../../../../common/src/Helper'); const EVENTS = require('./../../../../../src/share/Events').EVENTS; const Config = require('./../../../../../src/share/Config').Config; const OConfig = require('./../Config'); -const Operators = require('./../../../../../src/jsvm/Operators'); -const Num = require('./../../../../../src/jsvm/Num'); +const Operators = require('./../../../../vm/Operators'); +const Num = require('./../../../../vm/Num'); /** * {Function} Just a shortcuts @@ -95,9 +95,9 @@ class OperatorsDos extends Operators { * Parses variable operator. Format: var = number|var. 'num' bits format: * TODO: * - * @param {Num} num Packed into number jsvm line - * @param {Number} line Current line in jsvm - * @return {Number} Parsed jsvm line string + * @param {Num} num Packed into number vm line + * @param {Number} line Current line in vm + * @return {Number} Parsed vm line string */ onVar(num, line) { const vars = this.vars; diff --git a/client/src/manager/plugins/organisms/garmin/Code2String.js b/client/src/manager/plugins/organisms/garmin/Code2String.js index 1cfeaeb..9da06ae 100644 --- a/client/src/manager/plugins/organisms/garmin/Code2String.js +++ b/client/src/manager/plugins/organisms/garmin/Code2String.js @@ -5,7 +5,7 @@ * * @author flatline */ -const Num = require('./../../../../jsvm/Num'); +const Num = require('./../../../../vm/Num'); /** * {Function} Just a shortcuts @@ -26,7 +26,7 @@ class Code2String { this._offsets = []; /** * {Object} These operator handlers should return string representation - * of numeric based byte jsvm. + * of numeric based byte vm. */ this._OPERATORS_CB = { 0 : this._onVar.bind(this), @@ -78,7 +78,7 @@ class Code2String { for (let i = 0; i < len; i++) { operator = operators[Num.getOperator(code[i])](code[i], i, len); // - // This jsvm is used for closing blocks for if, for and other + // This vm is used for closing blocks for if, for and other // blocked operators. // if (offsets[offsets.length - 1] === i && offsets.length > 0) { @@ -102,8 +102,8 @@ class Code2String { * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) * BITS_PER_VAR bits - variable index or all bits till the end for constant * - * @param {Num} num Packed into number jsvm line - * @return {String} Parsed jsvm line string + * @param {Num} num Packed into number vm line + * @return {String} Parsed vm line string */ _onVar(num) { const var1 = VAR1(num); diff --git a/client/src/manager/plugins/organisms/garmin/Operators.js b/client/src/manager/plugins/organisms/garmin/Operators.js index ab9e2ea..03d3bba 100644 --- a/client/src/manager/plugins/organisms/garmin/Operators.js +++ b/client/src/manager/plugins/organisms/garmin/Operators.js @@ -7,8 +7,8 @@ * @author flatline */ const Helper = require('./../../../../../../common/src/Helper'); -const Operators = require('./../../../../../../client/src/jsvm/Operators'); -const Num = require('./../../../../../../client/src/jsvm/Num'); +const Operators = require('./../../../../vm/Operators'); +const Num = require('./../../../../vm/Num'); const Config = require('./../../../../share/Config').Config; const OConfig = require('./../Config'); @@ -79,9 +79,9 @@ class OperatorsGarmin extends Operators { * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) * BITS_PER_VAR bits - variable index or all bits till the end for constant * - * @param {Num} num Packed into number jsvm line - * @param {Number} line Current line in jsvm - * @return {Number} Parsed jsvm line string + * @param {Num} num Packed into number vm line + * @param {Number} line Current line in vm + * @return {Number} Parsed vm line string */ onVar(num, line) { const vars = this.vars; diff --git a/client/src/jsvm/Num.js b/client/src/vm/Num.js similarity index 100% rename from client/src/jsvm/Num.js rename to client/src/vm/Num.js diff --git a/client/src/jsvm/NumSpec.js b/client/src/vm/NumSpec.js similarity index 100% rename from client/src/jsvm/NumSpec.js rename to client/src/vm/NumSpec.js diff --git a/client/src/jsvm/Operators.js b/client/src/vm/Operators.js similarity index 100% rename from client/src/jsvm/Operators.js rename to client/src/vm/Operators.js diff --git a/client/src/jsvm/JSVM.js b/client/src/vm/VM.js similarity index 93% rename from client/src/jsvm/JSVM.js rename to client/src/vm/VM.js index 56b1cd2..0fb5921 100644 --- a/client/src/jsvm/JSVM.js +++ b/client/src/vm/VM.js @@ -1,5 +1,6 @@ /** - * Implements organism's code logic. + * Simple Virtual Machine for DOS language. Runs code line by line till the + * last and calls operators associated callbacks. * TODO: explain here code one number format,... * * @author flatline @@ -9,7 +10,6 @@ */ const Helper = require('./../../../common/src/Helper'); const Observer = require('./../../../common/src/Observer'); -const Config = require('./../../src/share/Config').Config; const OConfig = require('./../manager/plugins/organisms/Config'); const EVENTS = require('./../../src/share/Events').EVENTS; const EVENT_AMOUNT = require('./../../src/share/Events').EVENT_AMOUNT; @@ -40,7 +40,7 @@ class JSVM extends Observer { this._operatorCls = operatorCls; /** * {Function} Callback, which is called on every organism - * jsvm iteration. On it's end. + * vm iteration. On it's end. */ this._onCodeEnd = codeEndCb; /** @@ -138,8 +138,8 @@ class JSVM extends Observer { } /** - * Does crossover between two parent byte codes. Takes second jsvm's code part - * (from start1 to end1 offset) and inserts it instead first jsvm code part (start...end). + * Does crossover between two parent byte codes. Takes second vm's code part + * (from start1 to end1 offset) and inserts it instead first vm code part (start...end). * For example: * code1 : [1,2,3] * code2 : [4,5,6] @@ -150,7 +150,7 @@ class JSVM extends Observer { * jsvm1.crossover(jsvm2) // [4,5,6] instead [2,3] ->, jsvm1 === [1,4,5,6] * * @param {JSVM} jsvm JSVM instance, from where we have to cut code part - * @returns {Number} Amount of changes in current (this) jsvm + * @returns {Number} Amount of changes in current (this) vm */ crossover(jsvm) { const rand = Helper.rand; @@ -225,7 +225,7 @@ class JSVM extends Observer { } /** - * Removes random generated number into byte jsvm at random position + * Removes random generated number into byte vm at random position */ removeLine() { this._code.splice(Helper.rand(this._code.length), 1); @@ -243,21 +243,19 @@ class JSVM extends Observer { } /** - * Generates default variables jsvm. It should be in ES5 version, because + * Generates default variables vm. It should be in ES5 version, because * speed is important. Amount of vars depends on OConfig.codeBitsPerVar config. - * @returns {Array} vars jsvm + * @returns {Array} vars vm * @private */ _getVars() { - if (this._vars && this._vars.length > 0) { - return this._vars - } + if (this._vars && this._vars.length > 0) {return this._vars} const len = Math.pow(2, OConfig.codeBitsPerVar); - let vars = new Array(len); const range = OConfig.codeVarInitRange; const range2 = range / 2; const rand = Helper.rand; + let vars = new Array(len); for (let i = 0; i < len; i++) { vars[i] = rand(range) - range2; diff --git a/client/src/jsvm/JSVMSpec.js b/client/src/vm/VMSpec.js similarity index 98% rename from client/src/jsvm/JSVMSpec.js rename to client/src/vm/VMSpec.js index 2c23a5e..7037510 100644 --- a/client/src/jsvm/JSVMSpec.js +++ b/client/src/vm/VMSpec.js @@ -5,12 +5,12 @@ describe("client/src/organism/JSVM", () => { let Config = require('./../share/Config').Config; let OConfig = require('./../manager/plugins/organisms/Config'); let api = require('./../share/Config').api; - let JSVM = require('./JSVM'); + let JSVM = require('./VM'); let Num = require('./Num'); let Operators = require('./Operators'); let cls = null; - it("Checking jsvm creation", () => { + it("Checking vm creation", () => { let flag = false; const obs = new Observer(1); const jsvm = new JSVM(() => flag = true, obs, () => {}); @@ -101,24 +101,24 @@ describe("client/src/organism/JSVM", () => { // get size () {return 1} // } // const obs = new Observer(1); - // const jsvm = new JSVM(() => {}, obs, () => {}); + // const vm = new JSVM(() => {}, obs, () => {}); // const coc = api.get('codeOperatorsCls'); // const yp = api.get('codeYieldPeriod'); // const fc = api.get('codeFitnessCls'); // // // // Small hack. Use of private field for this test only // // - // jsvm._code.push(0b1000000000000000000000000); + // vm._code.push(0b1000000000000000000000000); // api.set('codeYieldPeriod', 1); // api.set('codeFitnessCls', null); // api.set('codeOperatorsCls', ''); - // jsvm.run({alive: true}); + // vm.run({alive: true}); // expect(flag === '167772160').toEqual(true); // api.set('codeYieldPeriod', yp); // api.set('codeFitnessCls', fc); // api.set('codeOperatorsCls', coc); // - // jsvm.destroy(); + // vm.destroy(); // }); it("Checking crossover with increasing child code", () => { From 0119f778832effd6c2c261144f54576b0aff2d09 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 8 Dec 2017 00:15:59 +0200 Subject: [PATCH 015/291] Closed #77 --- client/src/manager/plugins/status/Config.js | 17 +++++++++++++++++ .../src/manager/plugins/{ => status}/Status.js | 15 +++++++++------ client/src/share/Config.js | 2 +- 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 client/src/manager/plugins/status/Config.js rename client/src/manager/plugins/{ => status}/Status.js (88%) diff --git a/client/src/manager/plugins/status/Config.js b/client/src/manager/plugins/status/Config.js new file mode 100644 index 0000000..e8bb97c --- /dev/null +++ b/client/src/manager/plugins/status/Config.js @@ -0,0 +1,17 @@ +/** + * Configuration of Status plugin + * + * @author flatline + */ +const Config = { + /** + * {Boolean} Shows/Hides messages in a console + */ + showMessages: true, + /** + * {Number} Delay in milliseconds between showing one status line + */ + period: 10000 +}; + +module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/Status.js b/client/src/manager/plugins/status/Status.js similarity index 88% rename from client/src/manager/plugins/Status.js rename to client/src/manager/plugins/status/Status.js index 0353fd4..2c1843c 100644 --- a/client/src/manager/plugins/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -3,16 +3,18 @@ * * @author flatline */ -const EVENTS = require('./../../share/Events').EVENTS; -const Config = require('./../../share/Config').Config; +const Configurable = require('./../../../../../common/src/Configurable'); +const EVENTS = require('./../../../share/Events').EVENTS; +const Config = require('./../../../share/Config').Config; +const StatusConfig = require('./Config'); const GREEN = 'color: #00aa00'; const RED = 'color: #aa0000'; -// TODO: move this value to Status plugin config -const PERIOD = 10000; -class Status { +class Status extends Configurable { constructor(manager) { + super(manager, {Config, cfg: StatusConfig}); + this._manager = manager; this._stamp = 0; this._ips = 0; @@ -28,10 +30,11 @@ class Status { } _onIps(ips, orgs) { + if (!StatusConfig.showMessages) {return} const stamp = Date.now(); this._onBeforeIps(ips, orgs); - if (stamp - this._stamp < PERIOD) {return} + if (stamp - this._stamp < StatusConfig.period) {return} const times = this._times || 1; const times1 = (times - 1) || 1; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index bc75324..59f14fd 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -32,7 +32,7 @@ ClientConfig.init({ 'Config', 'client/Client', 'Energy', - 'Status', + 'status/Status', 'ips/Ips', 'backup/Backup' ], From 72240714b52e6dd3ec8fce3bbb909a1fd48d178e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 8 Dec 2017 00:39:14 +0200 Subject: [PATCH 016/291] fixed tests --- client/src/manager/ManagerSpec.js | 10 +++++++++- client/src/manager/plugins/status/Status.js | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 2af478b..101897c 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -29,6 +29,7 @@ describe("client/src/manager/Manager", () => { beforeEach(() => { delete Config.ips; delete Config.organisms; + delete Config.status; }); beforeAll(() => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; @@ -83,6 +84,7 @@ describe("client/src/manager/Manager", () => { it("Checking creation of two managers", (done) => { const man1 = new Manager(false); delete Config.organisms; + delete Config.status; const man2 = new Manager(false); waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { @@ -99,7 +101,7 @@ describe("client/src/manager/Manager", () => { Config.worldWidth = 10; Config.worldHeight = 10; - for (let i = 0; i < amount; i++) {delete Config.organisms; mans.push(new Manager(false))} + for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} if (waitObj.done) { @@ -234,6 +236,7 @@ describe("client/src/manager/Manager", () => { const server = new Server(); const man1 = new Manager(false); delete Config.organisms; + delete Config.status; const man2 = new Manager(false); let iterated1 = false; let iterated2 = false; @@ -299,6 +302,7 @@ describe("client/src/manager/Manager", () => { const server = new Server(); const man1 = new Manager(false); delete Config.organisms; + delete Config.status; const man2 = new Manager(false); let iterated1 = 0; let iterated2 = 0; @@ -362,6 +366,7 @@ describe("client/src/manager/Manager", () => { const server = new Server(); const man1 = new Manager(false); delete Config.organisms; + delete Config.status; const man2 = new Manager(false); let iterated1 = 0; let iterated2 = 0; @@ -448,6 +453,7 @@ describe("client/src/manager/Manager", () => { server.run(); for (let i = 0; i < CLIENTS; i++) { delete Config.organisms; + delete Config.status; mans.push(man = new Manager(false)); man.run(() => ++amount === CLIENTS && (waitObj.done = true)); } @@ -484,6 +490,7 @@ describe("client/src/manager/Manager", () => { SConfig.maxConnections = CLIENTS; man1 = new Manager(false); delete Config.organisms; + delete Config.status; man2 = new Manager(false); server.run(); @@ -554,6 +561,7 @@ describe("client/src/manager/Manager", () => { SConfig.maxConnections = CLIENTS; man1 = new Manager(false); delete Config.organisms; + delete Config.status; man2 = new Manager(false); server.run(); diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 2c1843c..81def18 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -29,6 +29,13 @@ class Status extends Configurable { manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); } + destroy() { + this._manager = null; + this._oldValues = null; + this._speed = null; + super.destroy(); + } + _onIps(ips, orgs) { if (!StatusConfig.showMessages) {return} const stamp = Date.now(); From d9122130e79c153e28fc825dcf1837efef10716c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 9 Dec 2017 00:23:56 +0200 Subject: [PATCH 017/291] working on distributed servers logic #13 --- client/src/manager/plugins/client/Client.js | 90 ++++++-------------- common/src/net/Client.js | 94 +++++++++++++++++++++ server/src/server/AroundServers.js | 3 - server/src/server/plugins/ApiSpec.js | 2 +- 4 files changed, 121 insertions(+), 68 deletions(-) create mode 100644 common/src/net/Client.js diff --git a/client/src/manager/plugins/client/Client.js b/client/src/manager/plugins/client/Client.js index 266621c..76b19d9 100644 --- a/client/src/manager/plugins/client/Client.js +++ b/client/src/manager/plugins/client/Client.js @@ -2,48 +2,35 @@ * Manager's plugin. Implements WebSocket client logic. Work in pair with * server/src/server/Server class. Activates current manager on a server * side and run it. - * TODO: this plugin should listen organisms moves outside of the world - * TODO: and send appropriate requests - * TODO: we have to use events in this class * * @author flatline */ -const Config = require('./../../../share/Config').Config; -const Helper = require('./../../../../../common/src/Helper'); -const TYPES = require('./../../../../../common/src/net/Requests').TYPES; -const Console = require('./../../../share/Console'); -const Connection = require('./../../../../../common/src/net/Connection').Connection; -const EVENTS = require('./../../../../../common/src/net/Connection').EVENTS; -const Plugins = require('./Plugins'); -const GEVENTS = require('./../../../share/Events').EVENTS; -// -// In browser we use browser's native WS implementation. On node.js -// we use implementation of 'ws' library -// -const WS = Config.modeNodeJs ? require('ws') : window.WebSocket; -// TODO: should be moved to local config -const PLUGINS = [ +const Config = require('./../../../share/Config').Config; +const Helper = require('./../../../../../common/src/Helper'); +const TYPES = require('./../../../../../common/src/net/Requests').TYPES; +const Console = require('./../../../share/Console'); +const BaseClient = require('./../../../../../common/src/net/Client').Client; +const EVENTS = require('./../../../../../common/src/net/Client').EVENTS; +const Plugins = require('./Plugins'); +const GEVENTS = require('./../../../share/Events').EVENTS; + +const PLUGINS = [ 'src/plugins/Request', 'src/manager/plugins/client/plugins/Api', 'src/manager/plugins/client/plugins/Async' ]; const EVENTS_LEN = Object.keys(EVENTS).length; -const OPEN = EVENTS_LEN; -const GET_ID = EVENTS_LEN + 1; +const GET_ID = EVENTS_LEN; const CLIENT_EVENTS = Object.assign({ - OPEN, GET_ID }, EVENTS); -const CLIENT_EVENTS_LEN = Object.keys(CLIENT_EVENTS).length; -class Client extends Connection { - // TODO: rename to parent +class Client extends BaseClient { constructor(manager) { - super(CLIENT_EVENTS_LEN); + super(Config.serverHost, Config.serverPort, Config.modeNodeJs, CLIENT_EVENTS); this.EVENTS = CLIENT_EVENTS; - // TODO: rename to _parent this._manager = manager; this._onStepOutCb = this._onStepOut.bind(this); this._runCb = this.run.bind(this); @@ -60,37 +47,26 @@ class Client extends Connection { run() { if (this.active) {return} - this._client = this._createWebSocket(); - this._client.onerror = this.onError.bind(this); - this._client.onclose = this.onClose.bind(this); - this._client.onopen = this.onOpen.bind(this); + super.run(); this._manager.on(GEVENTS.STEP_OUT, this._onStepOutCb); } stop() { - this.active && this._client.close(); + super.stop(); this._manager.off(GEVENTS.STEP_OUT, this._onStepOutCb); } - // TODO: rename to parent() get manager() {return this._manager} - get socket() {return this._client} destroy() { - this.stop(); - if (this._client) { - this._client.onclose = null; - this._client.onmessage = null; - this._client.onerror = null; - } + super.destroy(); + Helper.unoverride(this._manager, 'run', this._runCb); Helper.unoverride(this._manager, 'stop', this._stopCb); - this._runCb = null; - this._stopCb = null; - this._manager = null; - this._plugins = null; - - super.destroy(); + this._runCb = null; + this._stopCb = null; + this._manager = null; + this._plugins = null; } /** @@ -101,9 +77,8 @@ class Client extends Connection { */ onClose(event) { super.onClose(event); - this.active = false; - this._manager.clientId = null; Console.warn(`Client "${this._manager.clientId}" has disconnected by reason: ${this.closeReason}`); + this._manager.clientId = null; } /** @@ -112,13 +87,12 @@ class Client extends Connection { * @override */ onOpen(event) { - this.active = true; - this._client.onmessage = this.onMessage.bind(this, this._client); + super.onOpen(event); // // First we send request to get unique clientId from server. It // also means that this client is active and ready to run // - this.request(this._client, TYPES.REQ_GET_ID, (type, clientId) => { + this.request(this.socket, TYPES.REQ_GET_ID, (type, clientId) => { if (type !== TYPES.RES_GET_ID_OK) { Console.error(`Unable to get unique client id from server. Response type: ${type}`); return; @@ -127,24 +101,12 @@ class Client extends Connection { this.fire(GET_ID, clientId); Console.info(`Client id "${clientId}" obtained from the server`); }); - this.fire(OPEN, event); Console.info('Connection with Server has opened'); } - _createWebSocket() { - let ws = null; - try { - ws = new WS(`${Config.serverHost}:${Config.serverPort}`); - } catch (e) { - Console.error(e.message); - } - - return ws; - } - _onStepOut(x, y, dir, org) { - this.request(this._client, TYPES.REQ_MOVE_ORG, this._manager.clientId, x, y, dir, org.serialize()); + this.request(this.socket, TYPES.REQ_MOVE_ORG, this._manager.clientId, x, y, dir, org.serialize()); } } -module.exports = {Client, EVENTS: CLIENT_EVENTS}; +module.exports = {Client, EVENTS: CLIENT_EVENTS}; \ No newline at end of file diff --git a/common/src/net/Client.js b/common/src/net/Client.js new file mode 100644 index 0000000..dfe8c3d --- /dev/null +++ b/common/src/net/Client.js @@ -0,0 +1,94 @@ +/** + * Base class for clients. Implements WebSocket client logic. Work in pair with + * server/src/server/Server class. Work in browser and under Node.js. + * + * @author flatline + */ +const Connection = require('./../../../common/src/net/Connection').Connection; +const EVENTS = require('./../../../common/src/net/Connection').EVENTS; +const EVENTS_LEN = Object.keys(EVENTS).length; +const OPEN = EVENTS_LEN; + +const CLIENT_EVENTS = Object.assign({ + OPEN +}, EVENTS); + +class Client extends Connection { + /** + * @param {String} host Host of server + * @param {Number} port Port number + * @param {Boolean} nodeJs true if client is running under Node.js + * @param {Object} events Events map + */ + constructor(host, port, nodeJs, events) { + super(Object.keys(events).length); + this.EVENTS = events; + this._host = host; + this._port = port; + this._nodeJs = nodeJs; + } + + run() { + if (this.active) {return} + this._client = this._createWebSocket(); + this._client.onerror = this.onError.bind(this); + this._client.onclose = this.onClose.bind(this); + this._client.onopen = this.onOpen.bind(this); + } + + stop() {this.active && this._client.close()} + + get socket() {return this._client} + + destroy() { + this.stop(); + if (this._client) { + this._client.onclose = null; + this._client.onmessage = null; + this._client.onerror = null; + } + + super.destroy(); + } + + /** + * Is called on connection close with server. Close reason will be in + * this.closeReason field after calling super.onClose() method + * @param {Event} event + * @override + */ + onClose(event) { + super.onClose(event); + this.active = false; + } + + /** + * Is called after client has connected to the server + * @param {Event} event + * @override + */ + onOpen(event) { + this.active = true; + this._client.onmessage = this.onMessage.bind(this, this._client); + this.fire(OPEN, event); + } + + _createWebSocket() { + // + // In browser we use browser's native WS implementation. Under Node.js + // we use implementation of 'ws' library + // + const WS = this._nodeJs ? require('ws') : window.WebSocket; + let client = null; + + try { + client = new WS(`${this._host}:${this._port}`); + } catch (e) { + this.fire(this.EVENTS.ERR, e.message); + } + + return client; + } +} + +module.exports = {Client, EVENTS: CLIENT_EVENTS}; \ No newline at end of file diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 66783d7..c72d653 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -30,9 +30,6 @@ class AroundServers { this._socks = null; } - // TODO: rename to 'clients' - get socks() {return this._socks} - setSocket(sock, dir) { this._socks[dir] = sock; } diff --git a/server/src/server/plugins/ApiSpec.js b/server/src/server/plugins/ApiSpec.js index 72fde32..f14d996 100644 --- a/server/src/server/plugins/ApiSpec.js +++ b/server/src/server/plugins/ApiSpec.js @@ -12,7 +12,6 @@ describe("server/src/server/plugins/Api", () => { const Console = require('./../../../../client/src/share/Console'); const SConsole = require('./../../share/Console'); const Helper = require('./../../../../common/tests/Helper'); - const Request = require('./../../../../common/src/plugins/Request'); const Api = require('./Api'); const waitEvent = Helper.waitEvent; const host = Config.serverHost; @@ -26,6 +25,7 @@ describe("server/src/server/plugins/Api", () => { beforeAll(() => { Config.serverHost = 'ws://127.0.0.1'; + Config.modeNodeJs = true; error = Console.error; warn = Console.warn; info = Console.info; From ab5307e63290b6a3276e8d42dd610ebb161a4e4c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 9 Dec 2017 16:03:34 +0200 Subject: [PATCH 018/291] Client class refactoring working on distributes servers logic #13 --- client/src/manager/plugins/client/Client.js | 2 +- common/src/net/Client.js | 4 +- .../src/plugins/AsyncClient.js | 19 +++-- common/src/plugins/AsyncParent.js | 4 +- server/src/server/AroundServers.js | 75 +++++++++++++++---- server/src/server/Client.js | 58 ++++++++++++++ server/src/server/Server.js | 1 + server/src/share/Config.js | 32 ++++++-- 8 files changed, 163 insertions(+), 32 deletions(-) rename client/src/manager/plugins/client/plugins/Async.js => common/src/plugins/AsyncClient.js (81%) create mode 100644 server/src/server/Client.js diff --git a/client/src/manager/plugins/client/Client.js b/client/src/manager/plugins/client/Client.js index 76b19d9..c69bab4 100644 --- a/client/src/manager/plugins/client/Client.js +++ b/client/src/manager/plugins/client/Client.js @@ -17,7 +17,7 @@ const GEVENTS = require('./../../../share/Events').EVENTS; const PLUGINS = [ 'src/plugins/Request', 'src/manager/plugins/client/plugins/Api', - 'src/manager/plugins/client/plugins/Async' + 'src/plugins/AsyncClient' ]; const EVENTS_LEN = Object.keys(EVENTS).length; diff --git a/common/src/net/Client.js b/common/src/net/Client.js index dfe8c3d..cfa0768 100644 --- a/common/src/net/Client.js +++ b/common/src/net/Client.js @@ -20,9 +20,9 @@ class Client extends Connection { * @param {Boolean} nodeJs true if client is running under Node.js * @param {Object} events Events map */ - constructor(host, port, nodeJs, events) { + constructor(host, port, nodeJs, events = null) { super(Object.keys(events).length); - this.EVENTS = events; + this.EVENTS = events || CLIENT_EVENTS; this._host = host; this._port = port; this._nodeJs = nodeJs; diff --git a/client/src/manager/plugins/client/plugins/Async.js b/common/src/plugins/AsyncClient.js similarity index 81% rename from client/src/manager/plugins/client/plugins/Async.js rename to common/src/plugins/AsyncClient.js index 68e1d4d..aa63b31 100644 --- a/client/src/manager/plugins/client/plugins/Async.js +++ b/common/src/plugins/AsyncClient.js @@ -1,14 +1,16 @@ /** - * Implements asynchronous interface of `Async` class for `Client'. See - * `common/src/plugins/Async` class for details. + * Implements asynchronous interface of `AsyncChild` class for `Client'. See + * `common/src/plugins/AsyncChild` class for details. It tracks client states + * like 'running', 'stopping', 'failed' etc and adds appropriate methods to + * parent: isRunning(), isStopping(),... * * @author flatline */ -const AsyncChild = require('./../../../../../../common/src/plugins/AsyncChild'); -const Helper = require('./../../../../../../common/src/Helper'); +const AsyncChild = require('./AsyncChild'); +const Helper = require('./../Helper'); -class Async extends AsyncChild { - constructor(parent) { +class AsyncClient extends AsyncChild { + constructor(parent, cfg = null) { super(parent); const EVENTS = parent.EVENTS; @@ -16,13 +18,14 @@ class Async extends AsyncChild { this._running = false; this._stopping = false; this._failed = false; + this._openEvent = cfg && cfg.openEvent || EVENTS.GET_ID; this._onOpenCb = this._onOpen.bind(this); this._onCloseCb = this._onClose.bind(this); this._onRunCb = this._onRun.bind(this); this._onStopCb = this._onStop.bind(this); - parent.on(EVENTS.GET_ID, this._onOpenCb); + parent.on(this._openEvent, this._onOpenCb); parent.on(EVENTS.CLOSE, this._onCloseCb); parent.on(EVENTS.DESTROY, this._onCloseCb); @@ -95,4 +98,4 @@ class Async extends AsyncChild { } } -module.exports = Async; \ No newline at end of file +module.exports = AsyncClient; \ No newline at end of file diff --git a/common/src/plugins/AsyncParent.js b/common/src/plugins/AsyncParent.js index 802fe29..52af0c8 100644 --- a/common/src/plugins/AsyncParent.js +++ b/common/src/plugins/AsyncParent.js @@ -18,10 +18,10 @@ const WAIT_TIMEOUT_MS = 35000; const CHECK_INTERVAL_MS = 50; class AsyncParent { - constructor(parent, cfg = {}) { + constructor(parent, cfg = {}, classes = null) { this._parent = parent; this._cfg = cfg; - this._plugins = parent.plugins; + this._plugins = classes || parent.plugins; this._destroying = false; this._done = null; /** diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index c72d653..769b174 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -1,33 +1,59 @@ /** * This class stores logic of communication with nearest servers (up, right, * down and left), which are connected to current one. It keeps connections - * to them and updates active status. + * to them and updates active status. There are two types of connection with + * servers ans saving their sockets: + * 1. create local clients and connect them to remote servers + * 2. catch input connection from remote client + * + * The type of connection depends on who was created first and last. First + * created server A, which is above second created server B should do nothing. + * Server B should create four clients and connect them to A and other nearest + * servers, if they exist. For server A, input client connection from bottom + * will be stored in this._socks[DIR.DOWN]. The same scenario for right, down + * and left servers as well. * * @author flatline */ -const DIR = require('./../../../common/src/Directions').DIR; -const TYPES = require('./../../../common/src/net/Requests').TYPES; +const DIR = require('./../../../common/src/Directions').DIR; +const TYPES = require('./../../../common/src/net/Requests').TYPES; +const Client = require('./../../../common/src/net/Client').Client; class AroundServers { constructor(parent) { /** * {Connection} Connection instance of current Client or Server */ - this._parent = parent; + this._parent = parent; + /** + * {Object} Four sockets for sending messages to nearest servers. + * They may be: clients created within current class or sockets + * obtained after input client connection (created by remote server). + */ + this._socks = new Array(4); + /** + * {Object} Optional clients for connection with nearest servers. + * This map may be empty ar partly empty if servers around make + * connection first. Keys - directions, values - client instances. + */ + this._clients = new Array(4); /** - * {Object} All nearest servers by direction + * {AsyncParent} Keep reference to AsyncParent class, which tracks + * async running of classes through AsyncChild interface. */ - // TODO: rename to _clients. It should be a map of Client instances - this._socks = {}; - this._socks[DIR.UP] = null; - this._socks[DIR.RIGHT] = null; - this._socks[DIR.DOWN] = null; - this._socks[DIR.LEFT] = null; + this._async = null; + // + // Try to create clients map for connection with nearest servers + // + // TODO: uncomment this! + //this._createClients(); } - destroy() { - this._parent = null; - this._socks = null; + destroy(done = () => {}) { + this._parent = null; + this._socks = null; + this._clients = null; + this._async.destroy(done); } setSocket(sock, dir) { @@ -48,6 +74,27 @@ class AroundServers { socks[DOWN] && parent.request(socks[DOWN], ACTIVE, UP, activate); socks[LEFT] && parent.request(socks[LEFT], ACTIVE, RIGHT, activate); } + + _createClients() { + const cfg = this._parent.cfg; + const nodeJs = cfg.modeNodeJs; + const socks = this._socks; + const clients = this._clients; + const UP = DIR.UP; + const RIGHT = DIR.RIGHT; + const DOWN = DIR.DOWN; + const LEFT = DIR.LEFT; + + !socks[UP] && (clients[UP] = new Client(cfg.upHost, cfg.upPort, nodeJs)); + !socks[RIGHT] && (clients[RIGHT] = new Client(cfg.rightHost, cfg.rightPort, nodeJs)); + !socks[DOWN] && (clients[DOWN] = new Client(cfg.downHost, cfg.downPort, nodeJs)); + !socks[LEFT] && (clients[LEFT] = new Client(cfg.leftHost, cfg.leftPort, nodeJs)); + + this._async = new AsyncParent(this, {run: this._onDone.bind(this)}, clients); + clients.forEach((c) => c.run()); + } + + _onDone() {} } module.exports = AroundServers; \ No newline at end of file diff --git a/server/src/server/Client.js b/server/src/server/Client.js new file mode 100644 index 0000000..794d6b4 --- /dev/null +++ b/server/src/server/Client.js @@ -0,0 +1,58 @@ +/** + * Client, which created by server for connecting with nearest servers. + * + * @author flatline + */ +const Config = require('./../../../client/src/share/Config').Config; +const Helper = require('./../../../common/src/Helper'); +const NAMES = require('./../../../common/src/net/Requests').NAMES; +const Console = require('./../share/Console'); +const BaseClient = require('./../../../common/src/net/Client').Client; +const EVENTS = require('./../../../common/src/net/Client').EVENTS; +const Plugins = require('./Plugins'); + +const PLUGINS = [ + 'src/plugins/Request', + {path: 'src/plugins/AsyncClient', cfg: {openEvent: EVENTS.OPEN}} +]; + +class Client extends BaseClient { + constructor(dir, host, port) { + super(host, port, Config.modeNodeJs); + this._dir = dir; + // + // Plugins should be created at the end of constructor to + // have an ability to access this class public fields + // + this._plugins = new Plugins(this, {plugins: PLUGINS}); + } + + destroy() { + super.destroy(); + this._dir = null; + this._plugins = null; + } + + /** + * Is called on connection close with server. Close reason will be in + * this.closeReason field after calling super.onClose() method + * @param {Event} event + * @override + */ + onClose(event) { + super.onClose(event); + Console.warn(`Client "${NAMES[this._dir]}" has disconnected by reason: ${this.closeReason}`); + } + + /** + * Is called after client has connected to the server + * @param {Event} event + * @override + */ + onOpen(event) { + super.onOpen(event); + Console.info(`Client ${NAMES[this._dir]} has connected with Server`); + } +} + +module.exports = Client; \ No newline at end of file diff --git a/server/src/server/Server.js b/server/src/server/Server.js index f5b2eb1..f63b464 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -68,6 +68,7 @@ class Server extends Connection { constructor(port = Config.port) { super(SERVER_EVENTS_LEN); this.EVENTS = SERVER_EVENTS; + this.cfg = Config; this.conns = new Connections(Config.maxConnections); // TODO: This field should be used for connections with around servers. // TODO: We have to connect with all available around servers on start diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 05d3818..95221c2 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -37,15 +37,37 @@ ServerConfig.init({ */ port: 8099, /** - * TODO: this config should be obtained from Admin server or from command line - * TODO: parameters in future cmd line parser + * {String} Host address of server above. Shouldn't contain port */ upHost: 'ws://127.0.0.1', /** - * TODO: this config should be obtained from Admin server or from command line - * TODO: parameters in future cmd line parser + * {Number} Port number of server above */ - upPort: 8099 + upPort: 8099, + /** + * {String} Host address of server on the right. Shouldn't contain port + */ + rightHost: 'ws://127.0.0.1', + /** + * {Number} Port number of server on the right + */ + rightPort: 8100, + /** + * {String} Host address of server below. Shouldn't contain port + */ + downHost: 'ws://127.0.0.1', + /** + * {Number} Port number of server below + */ + downPort: 8101, + /** + * {String} Host address of server on the left. Shouldn't contain port + */ + leftHost: 'ws://127.0.0.1', + /** + * {Number} Port number of server on the left + */ + leftPort: 8102 }); module.exports = {Config: ServerConfig.cfg(), api: ServerConfig}; \ No newline at end of file From 7d240c92e6c10c4258114f01a6d880153c80043d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 10 Dec 2017 13:03:44 +0200 Subject: [PATCH 019/291] working on distributed servers logic #13 --- client/src/manager/ManagerSpec.js | 1 + common/src/net/Client.js | 2 +- common/src/net/Connection.js | 4 -- common/src/plugins/AsyncParent.js | 24 +++++++++--- server/src/App.js | 5 ++- server/src/server/AroundServers.js | 59 +++++++++++++++++++----------- server/src/server/Client.js | 4 +- server/src/server/Server.js | 3 -- 8 files changed, 63 insertions(+), 39 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 101897c..d60d05a 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -35,6 +35,7 @@ describe("client/src/manager/Manager", () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; Config.serverHost = 'ws://127.0.0.1'; Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); + Config.modeNodeJs = true; error = Console.error; warn = Console.warn; info = Console.info; diff --git a/common/src/net/Client.js b/common/src/net/Client.js index cfa0768..6887567 100644 --- a/common/src/net/Client.js +++ b/common/src/net/Client.js @@ -21,7 +21,7 @@ class Client extends Connection { * @param {Object} events Events map */ constructor(host, port, nodeJs, events = null) { - super(Object.keys(events).length); + super(Object.keys(events || CLIENT_EVENTS).length); this.EVENTS = events || CLIENT_EVENTS; this._host = host; this._port = port; diff --git a/common/src/net/Connection.js b/common/src/net/Connection.js index bb2e2b7..47cc7ff 100644 --- a/common/src/net/Connection.js +++ b/common/src/net/Connection.js @@ -63,7 +63,6 @@ class Connection extends Observer { * @param {Number} type Request type (see Requests.TYPES) * @param {*} params Array of parameters * @return {Number} Unique request id - * @abstract */ request(sock, type, ...params) {this.fire(REQUEST, sock, type, ...params)} @@ -74,7 +73,6 @@ class Connection extends Observer { * @param {Number} type Request type (see Requests.TYPES) * @param {Number} reqId Unique request id, returned by send() method * @param {Array} params Custom parameters to send - * @abstract */ response(sock, type, reqId, ...params) {this.fire(RESPONSE, sock, type, reqId, ...params)} @@ -82,7 +80,6 @@ class Connection extends Observer { * Is called every time if server/client sends us a request or response (response). * @param {WebSocket} sock Socket, received the message * @param {Event} event Message event. Data is in 'data' property - * @abstract */ onMessage(sock, event) { this.fire(MSG, sock, event); @@ -91,7 +88,6 @@ class Connection extends Observer { /** * Is called on every error during web sockets work * @param {Event} event Error event - * @abstract */ onError(event) { this.fire(ERR, event); diff --git a/common/src/plugins/AsyncParent.js b/common/src/plugins/AsyncParent.js index 52af0c8..b5a35a8 100644 --- a/common/src/plugins/AsyncParent.js +++ b/common/src/plugins/AsyncParent.js @@ -11,17 +11,17 @@ * @author flatline */ /** - * {Number} Amount of milliseconds we are waiting for one plugin to start or + * {Number} Amount of nanoseconds we are waiting for one plugin to start or * stop. In case of timeout exception will be thrown. */ -const WAIT_TIMEOUT_MS = 35000; +const WAIT_TIMEOUT_NS = 35 * 1e9; const CHECK_INTERVAL_MS = 50; class AsyncParent { - constructor(parent, cfg = {}, classes = null) { + constructor(parent, cfg = {}) { this._parent = parent; this._cfg = cfg; - this._plugins = classes || parent.plugins; + this._plugins = cfg.classes || parent.plugins; this._destroying = false; this._done = null; /** @@ -59,7 +59,7 @@ class AsyncParent { for (let p of plugins) { if (p.isAsync) { - const id = Date.now(); + const id = this._now(); waitMap[id] = setInterval(this._onInterval.bind(this, id, p, run, done), CHECK_INTERVAL_MS); } } @@ -69,12 +69,24 @@ class AsyncParent { _onInterval(id, plugin, run, done) { if (plugin.isFailed() || plugin.isActive() === run) {this._clearWaiter(id)} if (!this._hasWaiters()) {return this._onDone(run, done)} - if (Date.now() - id > WAIT_TIMEOUT_MS) { + if (this._now() - id > WAIT_TIMEOUT_NS) { this._clearWaiter(id); throw `Async waiting timeout. Plugin: ${plugin.constructor.name}`; } } + /** + * Returns time stamp in nanoseconds. Works under browser and Node.js + * @return {Number} Nanoseconds time stamp + */ + _now() { + if (this._cfg.isBrowser) { + return window.performance.now(); + } + const now = process.hrtime(); + return now[0] * 1e9 + now[1]; + } + _clearWaiter(id) { clearInterval(this._waitMap[id]); delete this._waitMap[id]; diff --git a/server/src/App.js b/server/src/App.js index 6bc0c2d..4f763ae 100644 --- a/server/src/App.js +++ b/server/src/App.js @@ -6,6 +6,9 @@ */ const Server = require('./server/Server').Server; const Config = require('./share/Config').Config; - +// +// Server always run under Node.js +// +Config.modeNodeJs = true; const server = new Server(Config.port); server.run(); \ No newline at end of file diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 769b174..7919e1c 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -15,10 +15,12 @@ * * @author flatline */ -const DIR = require('./../../../common/src/Directions').DIR; -const TYPES = require('./../../../common/src/net/Requests').TYPES; -const Client = require('./../../../common/src/net/Client').Client; +const DIR = require('./../../../common/src/Directions').DIR; +const TYPES = require('./../../../common/src/net/Requests').TYPES; +const AsyncParent = require('./../../../common/src/plugins/AsyncParent'); +const Client = require('./Client'); +// TODO: later here should be auto connect mechanism for this._clients class AroundServers { constructor(parent) { /** @@ -45,15 +47,27 @@ class AroundServers { // // Try to create clients map for connection with nearest servers // - // TODO: uncomment this! - //this._createClients(); + this._createClients(); + } + + run(done = () => {}) { + this._clients.forEach(c => c.run()); + this._async.run(done); + } + + stop(done = () => {}) { + this._clients.forEach(c => c.stop()); + this._async.stop(done); } destroy(done = () => {}) { - this._parent = null; - this._socks = null; - this._clients = null; - this._async.destroy(done); + this.stop(() => { + this._parent = null; + this._socks = null; + this._clients.forEach(c => c.destroy()); + this._clients = null; + this._async.destroy(done); + }); } setSocket(sock, dir) { @@ -77,24 +91,25 @@ class AroundServers { _createClients() { const cfg = this._parent.cfg; - const nodeJs = cfg.modeNodeJs; - const socks = this._socks; const clients = this._clients; - const UP = DIR.UP; - const RIGHT = DIR.RIGHT; - const DOWN = DIR.DOWN; - const LEFT = DIR.LEFT; - !socks[UP] && (clients[UP] = new Client(cfg.upHost, cfg.upPort, nodeJs)); - !socks[RIGHT] && (clients[RIGHT] = new Client(cfg.rightHost, cfg.rightPort, nodeJs)); - !socks[DOWN] && (clients[DOWN] = new Client(cfg.downHost, cfg.downPort, nodeJs)); - !socks[LEFT] && (clients[LEFT] = new Client(cfg.leftHost, cfg.leftPort, nodeJs)); + clients[DIR.UP] = new Client(cfg.upHost, cfg.upPort, true); + clients[DIR.RIGHT] = new Client(cfg.rightHost, cfg.rightPort, true); + clients[DIR.DOWN] = new Client(cfg.downHost, cfg.downPort, true); + clients[DIR.LEFT] = new Client(cfg.leftHost, cfg.leftPort, true); - this._async = new AsyncParent(this, {run: this._onDone.bind(this)}, clients); - clients.forEach((c) => c.run()); + this._addHandlers(clients); + this._async = new AsyncParent(this, {classes: clients, isBrowser: false}); } - _onDone() {} + _addHandlers(clients) { + const socks = this._socks; + + clients.forEach((c, i) => { + c.on(c.EVENTS.OPEN, () => socks[i] = c.socket); + c.on(c.EVENTS.CLOSE, () => socks[i] = null); + }); + } } module.exports = AroundServers; \ No newline at end of file diff --git a/server/src/server/Client.js b/server/src/server/Client.js index 794d6b4..d424273 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -5,7 +5,7 @@ */ const Config = require('./../../../client/src/share/Config').Config; const Helper = require('./../../../common/src/Helper'); -const NAMES = require('./../../../common/src/net/Requests').NAMES; +const NAMES = require('./../../../common/src/Directions').NAMES; const Console = require('./../share/Console'); const BaseClient = require('./../../../common/src/net/Client').Client; const EVENTS = require('./../../../common/src/net/Client').EVENTS; @@ -18,7 +18,7 @@ const PLUGINS = [ class Client extends BaseClient { constructor(dir, host, port) { - super(host, port, Config.modeNodeJs); + super(host, port, true); this._dir = dir; // // Plugins should be created at the end of constructor to diff --git a/server/src/server/Server.js b/server/src/server/Server.js index f63b464..787c636 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -70,9 +70,6 @@ class Server extends Connection { this.EVENTS = SERVER_EVENTS; this.cfg = Config; this.conns = new Connections(Config.maxConnections); - // TODO: This field should be used for connections with around servers. - // TODO: We have to connect with all available around servers on start - // TODO: and set them into aroundServers.setSocket() this.aroundServers = new AroundServers(this); this._server = null; From d1efececf1d502db19c9583f83a0ba31866962cf Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 10 Dec 2017 18:07:56 +0200 Subject: [PATCH 020/291] working on distributed servers logic #13 --- client/src/manager/ManagerSpec.js | 5 +++ .../src/manager/plugins/client/ClientSpec.js | 4 +++ common/src/net/Client.js | 6 ++-- server/src/server/AroundServers.js | 10 +++--- server/src/server/Client.js | 16 ++++++--- server/src/server/Server.js | 34 +++++++++++-------- server/src/server/ServerSpec.js | 4 +++ server/src/server/plugins/ApiSpec.js | 4 +++ server/src/share/Config.js | 19 +++++++---- 9 files changed, 71 insertions(+), 31 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index d60d05a..0106889 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -23,6 +23,7 @@ describe("client/src/manager/Manager", () => { let serror; let swarn; let sinfo; + let dist; let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; @@ -36,6 +37,9 @@ describe("client/src/manager/Manager", () => { Config.serverHost = 'ws://127.0.0.1'; Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); Config.modeNodeJs = true; + dist = SConfig.modeDistributed; + SConfig.modeDistributed = false; + error = Console.error; warn = Console.warn; info = Console.info; @@ -62,6 +66,7 @@ describe("client/src/manager/Manager", () => { Config.plugIncluded.push('ips/Ips'); jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; Config.serverHost = host; + SConfig.modeDistributed = dist; }); it("Checking manager creation", (done) => { diff --git a/client/src/manager/plugins/client/ClientSpec.js b/client/src/manager/plugins/client/ClientSpec.js index cc889ec..7f792d3 100644 --- a/client/src/manager/plugins/client/ClientSpec.js +++ b/client/src/manager/plugins/client/ClientSpec.js @@ -25,6 +25,7 @@ describe("client/src/manager/plugins/Client", () => { let serror; let swarn; let sinfo; + let dist; beforeAll(() => { // @@ -33,6 +34,8 @@ describe("client/src/manager/plugins/Client", () => { isNodeJs = Config.modeNodeJs; Config.modeNodeJs = true; Config.serverHost = 'ws://127.0.0.1'; + dist = SConfig.modeDistributed; + SConfig.modeDistributed = false; Client = require('./Client').Client; CEVENTS = require('./Client').EVENTS; Server = require('./../../../../../server/src/server/Server').Server; @@ -64,6 +67,7 @@ describe("client/src/manager/plugins/Client", () => { Console.info = info; Config.serverHost = host; + SConfig.modeDistributed = dist; }); it("Checking client creation without server", (done) => { diff --git a/common/src/net/Client.js b/common/src/net/Client.js index 6887567..f8402aa 100644 --- a/common/src/net/Client.js +++ b/common/src/net/Client.js @@ -23,8 +23,8 @@ class Client extends Connection { constructor(host, port, nodeJs, events = null) { super(Object.keys(events || CLIENT_EVENTS).length); this.EVENTS = events || CLIENT_EVENTS; - this._host = host; - this._port = port; + this.host = host; + this.port = port; this._nodeJs = nodeJs; } @@ -82,7 +82,7 @@ class Client extends Connection { let client = null; try { - client = new WS(`${this._host}:${this._port}`); + client = new WS(`${this.host}:${this.port}`); } catch (e) { this.fire(this.EVENTS.ERR, e.message); } diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 7919e1c..7eefcbe 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -53,11 +53,13 @@ class AroundServers { run(done = () => {}) { this._clients.forEach(c => c.run()); this._async.run(done); + return true; } stop(done = () => {}) { this._clients.forEach(c => c.stop()); this._async.stop(done); + return true; } destroy(done = () => {}) { @@ -93,10 +95,10 @@ class AroundServers { const cfg = this._parent.cfg; const clients = this._clients; - clients[DIR.UP] = new Client(cfg.upHost, cfg.upPort, true); - clients[DIR.RIGHT] = new Client(cfg.rightHost, cfg.rightPort, true); - clients[DIR.DOWN] = new Client(cfg.downHost, cfg.downPort, true); - clients[DIR.LEFT] = new Client(cfg.leftHost, cfg.leftPort, true); + clients[DIR.UP] = new Client(DIR.UP, cfg.upHost, cfg.upPort, true); + clients[DIR.RIGHT] = new Client(DIR.RIGHT, cfg.rightHost, cfg.rightPort, true); + clients[DIR.DOWN] = new Client(DIR.DOWN, cfg.downHost, cfg.downPort, true); + clients[DIR.LEFT] = new Client(DIR.LEFT, cfg.leftHost, cfg.leftPort, true); this._addHandlers(clients); this._async = new AsyncParent(this, {classes: clients, isBrowser: false}); diff --git a/server/src/server/Client.js b/server/src/server/Client.js index d424273..40b33ca 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -3,8 +3,6 @@ * * @author flatline */ -const Config = require('./../../../client/src/share/Config').Config; -const Helper = require('./../../../common/src/Helper'); const NAMES = require('./../../../common/src/Directions').NAMES; const Console = require('./../share/Console'); const BaseClient = require('./../../../common/src/net/Client').Client; @@ -33,6 +31,16 @@ class Client extends BaseClient { this._plugins = null; } + /** + * Is called if error occurred + * @param {String} msg + * @override + */ + onError(msg) { + super.onError(msg); + Console.error(`'${NAMES[this._dir]}' server error: ${msg} on ${this.host}:${this.port}`); + } + /** * Is called on connection close with server. Close reason will be in * this.closeReason field after calling super.onClose() method @@ -41,7 +49,7 @@ class Client extends BaseClient { */ onClose(event) { super.onClose(event); - Console.warn(`Client "${NAMES[this._dir]}" has disconnected by reason: ${this.closeReason}`); + Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: ${this.closeReason} on ${this.host}:${this.port}`); } /** @@ -51,7 +59,7 @@ class Client extends BaseClient { */ onOpen(event) { super.onOpen(event); - Console.info(`Client ${NAMES[this._dir]} has connected with Server`); + Console.info(`'${NAMES[this._dir]}' server has connected on ${this.host}:${this.port}`); } } diff --git a/server/src/server/Server.js b/server/src/server/Server.js index 787c636..008008d 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -70,8 +70,8 @@ class Server extends Connection { this.EVENTS = SERVER_EVENTS; this.cfg = Config; this.conns = new Connections(Config.maxConnections); - this.aroundServers = new AroundServers(this); + this._aroundServers = Config.modeDistributed ? new AroundServers(this) : null; this._server = null; this._port = port; this._running = false; @@ -105,11 +105,14 @@ class Server extends Connection { Server.ports[this._port] = true; try { this._server = new WebSocket.Server({port: this._port}, () => { - this._server.on('connection', this.onConnect.bind(this)); - this.active = true; - this._running = false; - this.fire(RUN); - Console.info('Server is ready'); + const onDone = () => { + this._server.on('connection', this.onConnect.bind(this)); + this.active = true; + this._running = false; + this.fire(RUN); + Console.info('Server is ready'); + }; + this._aroundServers && this._aroundServers.run(onDone) || onDone(); }); } catch (e) { Console.warn(`Can\'t run server on port ${this._port}. Error: ${e.message}`); @@ -146,14 +149,17 @@ class Server extends Connection { try { me._stopping = true; me._server.close(() => { - delete Server.ports[me._port]; - me._server.removeAllListeners('connection'); - me.active = false; - me._stopping = false; - this._server = null; - me.fire(STOP); - Console.info('Server has stopped. All clients have disconnected'); - if (me._destroying) {me.destroy()} + const onDone = () => { + delete Server.ports[me._port]; + me._server.removeAllListeners('connection'); + me.active = false; + me._stopping = false; + this._server = null; + me.fire(STOP); + Console.info('Server has stopped. All clients have disconnected'); + if (me._destroying) {me.destroy()} + }; + this._aroundServers && this._aroundServers.stop(onDone) || onDone(); }); } catch(e) { Console.error('Server.stop() failed: ', e); diff --git a/server/src/server/ServerSpec.js b/server/src/server/ServerSpec.js index fcdc420..1fa5959 100644 --- a/server/src/server/ServerSpec.js +++ b/server/src/server/ServerSpec.js @@ -27,9 +27,12 @@ describe("server/src/server/Server", () => { let serror; let swarn; let sinfo; + let dist; beforeAll(() => { Config.serverHost = 'ws://127.0.0.1'; + dist = SConfig.modeDistributed; + SConfig.modeDistributed = false; error = Console.error; warn = Console.warn; info = Console.info; @@ -54,6 +57,7 @@ describe("server/src/server/Server", () => { Console.info = info; Config.modeNodeJs = OLD_MODE; Config.serverHost = host; + SConfig.modeDistributed = dist; }); it("Checking server creation", () => { diff --git a/server/src/server/plugins/ApiSpec.js b/server/src/server/plugins/ApiSpec.js index f14d996..3b4a35b 100644 --- a/server/src/server/plugins/ApiSpec.js +++ b/server/src/server/plugins/ApiSpec.js @@ -22,10 +22,13 @@ describe("server/src/server/plugins/Api", () => { let serror; let swarn; let sinfo; + let dist; beforeAll(() => { Config.serverHost = 'ws://127.0.0.1'; Config.modeNodeJs = true; + dist = SConfig.modeDistributed; + SConfig.modeDistributed = false; error = Console.error; warn = Console.warn; info = Console.info; @@ -50,6 +53,7 @@ describe("server/src/server/plugins/Api", () => { Console.info = info; Config.modeNodeJs = OLD_MODE; Config.serverHost = host; + SConfig.modeDistributed = dist; }); it("Checking unique id on client connect", (done) => { diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 95221c2..c765805 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -33,17 +33,24 @@ ServerConfig.init({ */ maxConnections: 100, /** - * {Number} Port number for connecting with server + * {Number} Port number for connecting with server. This value will be + * passed to the server during creation */ port: 8099, + /** + * {Boolean} Means, that this server will be run in distributed mode. And + * will be connected with near servers (up...left). false, means, that + * server will be run in single server mode (no near servers). + */ + modeDistributed: true, /** * {String} Host address of server above. Shouldn't contain port */ upHost: 'ws://127.0.0.1', /** - * {Number} Port number of server above + * {Number} Port number of server above. */ - upPort: 8099, + upPort: 8100, /** * {String} Host address of server on the right. Shouldn't contain port */ @@ -51,7 +58,7 @@ ServerConfig.init({ /** * {Number} Port number of server on the right */ - rightPort: 8100, + rightPort: 8101, /** * {String} Host address of server below. Shouldn't contain port */ @@ -59,7 +66,7 @@ ServerConfig.init({ /** * {Number} Port number of server below */ - downPort: 8101, + downPort: 8102, /** * {String} Host address of server on the left. Shouldn't contain port */ @@ -67,7 +74,7 @@ ServerConfig.init({ /** * {Number} Port number of server on the left */ - leftPort: 8102 + leftPort: 8103 }); module.exports = {Config: ServerConfig.cfg(), api: ServerConfig}; \ No newline at end of file From efb444d1e1080c35019727052bac0e1142d52fa8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 11 Dec 2017 00:36:59 +0200 Subject: [PATCH 021/291] added skeleton of nearest servers communication #13 --- common/src/net/Api.js | 1 - common/src/net/Requests.js | 15 ++++++----- server/src/server/AroundServers.js | 41 ++++++++++++++++++------------ server/src/server/Server.js | 6 ++--- server/src/server/plugins/Api.js | 30 +++++++++------------- 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/common/src/net/Api.js b/common/src/net/Api.js index bbaaaa6..74fd4fe 100644 --- a/common/src/net/Api.js +++ b/common/src/net/Api.js @@ -31,7 +31,6 @@ class Api { */ this.api = {}; this.parent = parent; - /** * {WebSocket} Currently active socket. It's available only during * message is received diff --git a/common/src/net/Requests.js b/common/src/net/Requests.js index 3184348..544f282 100644 --- a/common/src/net/Requests.js +++ b/common/src/net/Requests.js @@ -17,16 +17,17 @@ const TYPES = { // // Requests section // - REQ_MOVE_ORG : 0, - REQ_GIVE_ID : 1, - REQ_SET_NEAR_ACTIVE: 2, - REQ_GET_ID : 3, + REQ_MOVE_ORG : 0, + REQ_GIVE_ID : 1, + REQ_SET_NEAR_ACTIVE : 2, // Other (near) server wants to connect with current one + REQ_GET_ID : 3, // Client wants obtain it's unique id from server // // Responses section // - RES_MOVE_ERR : 1000, - RES_INVALID_TYPE : 1001, - RES_GET_ID_OK : 1002 + RES_MOVE_ERR : 1000, + RES_INVALID_TYPE : 1001, + RES_GET_ID_OK : 1002, + RES_SET_NEAR_ACTIVE_OK: 1003 }; module.exports = {TYPES, MASKS}; \ No newline at end of file diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 7eefcbe..a6056c4 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -16,9 +16,15 @@ * @author flatline */ const DIR = require('./../../../common/src/Directions').DIR; +const NAMES = require('./../../../common/src/Directions').NAMES; const TYPES = require('./../../../common/src/net/Requests').TYPES; const AsyncParent = require('./../../../common/src/plugins/AsyncParent'); const Client = require('./Client'); +/** + * {Array} Array of flipped directions. Is used for connecting with nearest + * servers: left -> right, up -> down, right -> left, down -> up + */ +const FLIP_DIR = [DIR.DOWN, DIR.LEFT, DIR.UP, DIR.RIGHT]; // TODO: later here should be auto connect mechanism for this._clients class AroundServers { @@ -76,21 +82,6 @@ class AroundServers { this._socks[dir] = sock; } - activate(activate = true) { - const socks = this._socks; - const parent = this._parent; - const UP = DIR.UP; - const RIGHT = DIR.RIGHT; - const DOWN = DIR.DOWN; - const LEFT = DIR.LEFT; - const ACTIVE = TYPES.REQ_SET_NEAR_ACTIVE; - - socks[UP] && parent.request(socks[UP], ACTIVE, DOWN, activate); - socks[RIGHT] && parent.request(socks[RIGHT], ACTIVE, LEFT, activate); - socks[DOWN] && parent.request(socks[DOWN], ACTIVE, UP, activate); - socks[LEFT] && parent.request(socks[LEFT], ACTIVE, RIGHT, activate); - } - _createClients() { const cfg = this._parent.cfg; const clients = this._clients; @@ -108,10 +99,28 @@ class AroundServers { const socks = this._socks; clients.forEach((c, i) => { - c.on(c.EVENTS.OPEN, () => socks[i] = c.socket); + c.on(c.EVENTS.OPEN, this._onOpen.bind(this, c, i)); c.on(c.EVENTS.CLOSE, () => socks[i] = null); }); } + /** + * Sends a request to tell remote server, that this client is + * for inter server communication only. dir parameter sets nearest + * server location (up...left) + * @param {WebSocket} client WebSocket client instance for connection + * with nearest server + * @param {Number} dir Direction of nearest server (up...left) + */ + _onOpen(client, dir) { + client.request(client.socket, TYPES.REQ_SET_NEAR_ACTIVE, FLIP_DIR[dir], (type) => { + if (type !== TYPES.RES_SET_NEAR_ACTIVE_OK) { + Console.error(`Unable to connect to '${NAMES[dir]}' server. Response type: ${type}`); + return; + } + this._socks[dir] = client.socket; + Console.info(`Connected with '${dir}' server`); + }); + } } module.exports = AroundServers; \ No newline at end of file diff --git a/server/src/server/Server.js b/server/src/server/Server.js index 008008d..fe5f9e0 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -70,8 +70,8 @@ class Server extends Connection { this.EVENTS = SERVER_EVENTS; this.cfg = Config; this.conns = new Connections(Config.maxConnections); + this.aroundServers = Config.modeDistributed ? new AroundServers(this) : null; - this._aroundServers = Config.modeDistributed ? new AroundServers(this) : null; this._server = null; this._port = port; this._running = false; @@ -112,7 +112,7 @@ class Server extends Connection { this.fire(RUN); Console.info('Server is ready'); }; - this._aroundServers && this._aroundServers.run(onDone) || onDone(); + this.aroundServers && this.aroundServers.run(onDone) || onDone(); }); } catch (e) { Console.warn(`Can\'t run server on port ${this._port}. Error: ${e.message}`); @@ -159,7 +159,7 @@ class Server extends Connection { Console.info('Server has stopped. All clients have disconnected'); if (me._destroying) {me.destroy()} }; - this._aroundServers && this._aroundServers.stop(onDone) || onDone(); + this.aroundServers && this.aroundServers.stop(onDone) || onDone(); }); } catch(e) { Console.error('Server.stop() failed: ', e); diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index b987c91..caeffbe 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -17,8 +17,9 @@ const BaseApi = require('./../../../../common/src/net/Api'); class Api extends BaseApi { constructor(parent) { super(parent); - this.api[TYPES.REQ_MOVE_ORG] = this._moveOrg.bind(this); - this.api[TYPES.REQ_GET_ID] = this._getId.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._moveOrg.bind(this); + this.api[TYPES.REQ_GET_ID] = this._getId.bind(this); + this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setNearServer.bind(this); this._onCloseCb = this._onClose.bind(this); @@ -63,20 +64,11 @@ class Api extends BaseApi { } /** - * Creates response with unique client id for just connected clients or servers + * Creates response with unique client id for just connected clients * @param {Number} reqId Unique request id. Needed for response - * @param {Boolean} isClient true for request from client, false for server * @api */ - _getId(reqId, isClient = true) { - isClient && this._onGetClientId(reqId) || this._onGetServerId(reqId); - } - - /** - * If it was a request from client, then we have to create unique clientId for him. - * @param {Number} reqId Unique request id - */ - _onGetClientId(reqId) { + _getId(reqId) { const sock = this.sock; const region = this.parent.conns.getFreeRegion(); const clientId = Connections.toId(region); @@ -88,17 +80,19 @@ class Api extends BaseApi { return; } this.parent.conns.setData(region, 'sock', sock); - this._setActive(clientId, true); + this._setActive(clientId, true); this.parent.response(sock, TYPES.RES_GET_ID_OK, reqId, clientId); Console.info(`Client ${clientId} has connected`); } /** - * If it was a server, then we have to update our "around" servers (this.parent.activeAround) - * @param {Number} reqId Unique request id + * Sets near server by direction + * @param {Number} reqId Unique request id. Needed for response + * @param {Number} dir Direction of incoming nearest server + * @api */ - _onGetServerId(reqId) { - // TODO: + _setNearServer(reqId, dir) { + this.parent.aroundServers.setSocket(this.sock, dir); } /** From 9940a8ad9cc9e488e49844bb3fe9755a1ffb042e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 11 Dec 2017 09:53:21 +0200 Subject: [PATCH 022/291] working on distributed servers logic #13 fixed console error if user runs app in 'single' mode --- client/src/manager/Manager.js | 7 ++++--- common/src/plugins/Plugins.js | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 48b6de3..341bd8b 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -85,9 +85,10 @@ class Manager extends Observer { // have an ability access Manager's API from them // this._plugins = new Plugins(this, { - plugins: Config.plugIncluded, - async : true, - run : this._onDone.bind(this) + plugins : Config.plugIncluded, + async : true, + run : this._onDone.bind(this), + isBrowser: true }); } diff --git a/common/src/plugins/Plugins.js b/common/src/plugins/Plugins.js index a563449..1b6bc16 100644 --- a/common/src/plugins/Plugins.js +++ b/common/src/plugins/Plugins.js @@ -31,7 +31,7 @@ class Plugins { if (cfg.async) { Helper.override(parent, 'run', this._onRunCb); Helper.override(parent, 'stop', this._onStopCb); - this._async = new AsyncParent(parent, {run: cfg.run}); + this._async = new AsyncParent(parent, {run: cfg.run, isBrowser: cfg.isBrowser}); } } From 21c553b208ba6e407407b78d27cc32f33684e1cf Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 11 Dec 2017 10:04:18 +0200 Subject: [PATCH 023/291] fixed tests --- client/src/manager/Manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 341bd8b..5d6e7a3 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -88,7 +88,7 @@ class Manager extends Observer { plugins : Config.plugIncluded, async : true, run : this._onDone.bind(this), - isBrowser: true + isBrowser: !Config.modeNodeJs }); } From 96d58d4afe63eccaafb73a08500ca047d0293ba3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 11 Dec 2017 17:28:12 +0200 Subject: [PATCH 024/291] fixed tests #83 working on distributed servers calculations #13 --- common/src/net/Requests.js | 7 +- server/src/server/Connections.js | 39 +++--- server/src/server/ConnectionsSpec.js | 199 +++++++++++++++++++++------ server/src/server/plugins/Api.js | 17 +-- 4 files changed, 187 insertions(+), 75 deletions(-) diff --git a/common/src/net/Requests.js b/common/src/net/Requests.js index 544f282..6da2c7d 100644 --- a/common/src/net/Requests.js +++ b/common/src/net/Requests.js @@ -17,10 +17,9 @@ const TYPES = { // // Requests section // - REQ_MOVE_ORG : 0, - REQ_GIVE_ID : 1, - REQ_SET_NEAR_ACTIVE : 2, // Other (near) server wants to connect with current one - REQ_GET_ID : 3, // Client wants obtain it's unique id from server + REQ_MOVE_ORG : 0, // Organism moves from one world(manager) to another(sibling) + REQ_SET_NEAR_ACTIVE : 1, // Other (near) server wants to connect with current one + REQ_GET_ID : 2, // Client wants obtain it's unique id from server // // Responses section // diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index 26e7f25..f3b3fa1 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -35,13 +35,7 @@ class Connections { } constructor(amount) { - /** - * {Number} amount Maximum amount of connections for current server. Should - * be quadratic (x^2) e.g.: 4, 9, 16,... This value will be extended - * with additional "around" rows and columns for connecting with sibling - * servers. So, result amount will be e.g.: 100 + 2 rows + 2 columns. - */ - this._amount = amount; + if (amount < 1) {throw `Incorrect amount of connections in class Connections - ${amount}`} /** * {Number} Size of one side of MAX_CONNECTIONS qub. Contains additional * "around" rows and columns. For qub == 16, it's 4. @@ -50,7 +44,7 @@ class Connections { /** * {Number} Size of one full side of the connections squire */ - this._side = +Math.sqrt(amount).toFixed() + 2; + this._side = +Math.sqrt(amount).toFixed(); for (let col = 0, conns = this.conns; col < this._side; col++) { conns[col] = (new Array(this._side)).fill(null); @@ -60,6 +54,7 @@ class Connections { destroy() { this.conns = null; + this._side = null; } /** @@ -68,8 +63,8 @@ class Connections { * @returns {Array|null} */ upRegion(region) { - region = region.slice(); - return --region[1] < 0 ? null : region; + (region = region.slice())[1]--; + return this._validRegion(region) && region || null; } /** @@ -78,8 +73,8 @@ class Connections { * @returns {Array|null} */ rightRegion(region) { - region = region.slice(); - return ++region[0] > this._amount + 1 ? null : region; + (region = region.slice())[0]++; + return this._validRegion(region) && region || null; } /** @@ -88,8 +83,8 @@ class Connections { * @returns {Array|null} */ downRegion(region) { - region = region.slice(); - return ++region[1] > this._amount + 1 ? null : region; + (region = region.slice())[1]++; + return this._validRegion(region) && region || null; } /** @@ -98,8 +93,8 @@ class Connections { * @returns {Array|null} */ leftRegion(region) { - region = region.slice(); - return --region[0] < 0 ? null : region; + (region = region.slice())[0]--; + return this._validRegion(region) && region || null; } /** @@ -108,7 +103,7 @@ class Connections { * @returns {Object|null} */ getConnection(region) { - return region && this.conns[region[0]][region[1]]; + return this._validRegion(region) && this.conns[region[0]][region[1]] || null; } /** @@ -129,10 +124,10 @@ class Connections { getFreeRegion() { const conns = this.conns; - const side = this._side - 1; + const side = this._side; - for (let col = 1; col < side; col++) { - for (let row = 1; row < side; row++) { + for (let col = 0; col < side; col++) { + for (let row = 0; row < side; row++) { if (conns[col][row].sock === null) { return [col, row]; } @@ -141,6 +136,10 @@ class Connections { return null; } + + _validRegion(region) { + return region && region[0] > -1 && region[0] < this._side && region[1] > -1 && region[1] < this._side; + } } diff --git a/server/src/server/ConnectionsSpec.js b/server/src/server/ConnectionsSpec.js index 895ed68..83e4aa5 100644 --- a/server/src/server/ConnectionsSpec.js +++ b/server/src/server/ConnectionsSpec.js @@ -6,6 +6,11 @@ describe("server/src/server/Connections", () => { let cons = new Connections(1); cons.destroy(); }); + it("Checking Connections instance creation with wrong amount of connections", () => { + expect(() => new Connections(0)).toThrow(); + expect(() => new Connections(-1)).toThrow(); + expect(() => new Connections(-100)).toThrow(); + }); it("Checking toId() method", () => { expect(Connections.toId([1,1])).toEqual('1-1'); expect(Connections.toId([0,0])).toEqual('0-0'); @@ -14,8 +19,8 @@ describe("server/src/server/Connections", () => { let cons = new Connections(1); let region = cons.getFreeRegion(); - expect(THelper.compare(region, [1, 1])).toEqual(true); - expect(Connections.toId(region)).toEqual('1-1'); + expect(THelper.compare(region, [0, 0])).toEqual(true); + expect(Connections.toId(region)).toEqual('0-0'); expect(Connections.toId([1,1])).toEqual('1-1'); expect(Connections.toId([0,0])).toEqual('0-0'); cons.destroy(); @@ -27,85 +32,193 @@ describe("server/src/server/Connections", () => { it("Checking upRegion() method", () => { let cons = new Connections(1); - expect(THelper.compare(cons.upRegion([1,1]), [1,0])).toEqual(true); - expect(THelper.compare(cons.upRegion([1,2]), [1,1])).toEqual(true); - expect(cons.upRegion([0,0]) === null).toEqual(true); - expect(cons.upRegion([1,0]) === null).toEqual(true); - expect(cons.upRegion([-1,0]) === null).toEqual(true); - expect(THelper.compare(cons.upRegion([-1,1]), [-1,0])).toEqual(true); + expect(cons.upRegion([0,0] )).toEqual(null); + expect(cons.upRegion([1,2] )).toEqual(null); + expect(cons.upRegion([1,0] )).toEqual(null); + expect(cons.upRegion([1,1] )).toEqual(null); + expect(cons.upRegion([-1,0] )).toEqual(null); + expect(cons.upRegion([-1,1] )).toEqual(null); + expect(cons.upRegion([-1,-1])).toEqual(null); + + cons.destroy(); + }); + it("Checking upRegion() method 2", () => { + let cons = new Connections(4); + + expect(cons.upRegion([0,0] )).toEqual(null); + expect(cons.upRegion([1,2] )).toEqual([1,1]); + expect(cons.upRegion([1,1] )).toEqual([1,0]); + expect(cons.upRegion([0,1] )).toEqual([0,0]); + expect(cons.upRegion([2,1] )).toEqual(null); + expect(cons.upRegion([1,0] )).toEqual(null); + expect(cons.upRegion([-1,0] )).toEqual(null); + expect(cons.upRegion([-1,1] )).toEqual(null); + expect(cons.upRegion([-1,-1])).toEqual(null); + expect(cons.upRegion([2,2] )).toEqual(null); cons.destroy(); }); it("Checking rightRegion() method", () => { let cons = new Connections(1); - expect(THelper.compare(cons.rightRegion([1,1]), [2,1])).toEqual(true); - expect(THelper.compare(cons.rightRegion([1,2]), [2,2])).toEqual(true); - expect(cons.rightRegion([2,0]) === null).toEqual(true); - expect(cons.rightRegion([2,1]) === null).toEqual(true); - expect(cons.rightRegion([2,-1]) === null).toEqual(true); - expect(THelper.compare(cons.rightRegion([1,-1]), [2,-1])).toEqual(true); + expect(cons.rightRegion([0,0] )).toEqual(null); + expect(cons.rightRegion([1,2] )).toEqual(null); + expect(cons.rightRegion([1,0] )).toEqual(null); + expect(cons.rightRegion([1,1] )).toEqual(null); + expect(cons.rightRegion([2,0] )).toEqual(null); + expect(cons.rightRegion([2,1] )).toEqual(null); + expect(cons.rightRegion([2,-1] )).toEqual(null); + expect(cons.rightRegion([1,-1] )).toEqual(null); + expect(cons.rightRegion([-1,-1])).toEqual(null); + + cons.destroy(); + }); + it("Checking rightRegion() method 2", () => { + let cons = new Connections(4); + + expect(cons.rightRegion([0,0] )).toEqual([1,0]); + expect(cons.rightRegion([1,2] )).toEqual(null); + expect(cons.rightRegion([2,0] )).toEqual(null); + expect(cons.rightRegion([2,1] )).toEqual(null); + expect(cons.rightRegion([1,1] )).toEqual(null); + expect(cons.rightRegion([0,1] )).toEqual([1,1]); + expect(cons.rightRegion([-1,1] )).toEqual([0,1]); + expect(cons.rightRegion([2,-1] )).toEqual(null); + expect(cons.rightRegion([1,-1] )).toEqual(null); + expect(cons.rightRegion([-1,-1])).toEqual(null); cons.destroy(); }); it("Checking downRegion() method", () => { let cons = new Connections(1); - expect(THelper.compare(cons.downRegion([1,1]), [1,2])).toEqual(true); - expect(THelper.compare(cons.downRegion([1,0]), [1,1])).toEqual(true); - expect(cons.downRegion([0,2]) === null).toEqual(true); - expect(cons.downRegion([1,2]) === null).toEqual(true); - expect(cons.downRegion([-1,2]) === null).toEqual(true); - expect(THelper.compare(cons.downRegion([-1,1]), [-1,2])).toEqual(true); + expect(cons.downRegion([0,0] )).toEqual(null); + expect(cons.downRegion([1,2] )).toEqual(null); + expect(cons.downRegion([1,0] )).toEqual(null); + expect(cons.downRegion([1,1] )).toEqual(null); + expect(cons.downRegion([2,0] )).toEqual(null); + expect(cons.downRegion([2,1] )).toEqual(null); + expect(cons.downRegion([2,-1] )).toEqual(null); + expect(cons.downRegion([1,-1] )).toEqual(null); + expect(cons.downRegion([-1,-1])).toEqual(null); + + cons.destroy(); + }); + it("Checking downRegion() method 2", () => { + let cons = new Connections(4); + + expect(cons.downRegion([0,0] )).toEqual([0,1]); + expect(cons.downRegion([1,2] )).toEqual(null); + expect(cons.downRegion([1,0] )).toEqual([1,1]); + expect(cons.downRegion([1,1] )).toEqual(null); + expect(cons.downRegion([2,0] )).toEqual(null); + expect(cons.downRegion([2,1] )).toEqual(null); + expect(cons.downRegion([2,-1] )).toEqual(null); + expect(cons.downRegion([1,-1] )).toEqual([1,0]); + expect(cons.downRegion([0,-1] )).toEqual([0,0]); + expect(cons.downRegion([-1,-1])).toEqual(null); cons.destroy(); }); it("Checking leftRegion() method", () => { let cons = new Connections(1); - expect(THelper.compare(cons.leftRegion([1,1]), [0,1])).toEqual(true); - expect(THelper.compare(cons.leftRegion([2,1]), [1,1])).toEqual(true); - expect(cons.leftRegion([0,0]) === null).toEqual(true); - expect(cons.leftRegion([0,1]) === null).toEqual(true); - expect(cons.leftRegion([0,-1]) === null).toEqual(true); - expect(THelper.compare(cons.leftRegion([1,-1]), [0,-1])).toEqual(true); + expect(cons.downRegion([0,0] )).toEqual(null); + expect(cons.downRegion([1,2] )).toEqual(null); + expect(cons.downRegion([1,0] )).toEqual(null); + expect(cons.downRegion([1,1] )).toEqual(null); + expect(cons.downRegion([2,0] )).toEqual(null); + expect(cons.downRegion([2,1] )).toEqual(null); + expect(cons.downRegion([2,-1] )).toEqual(null); + expect(cons.downRegion([1,-1] )).toEqual(null); + expect(cons.downRegion([-1,-1])).toEqual(null); + + cons.destroy(); + }); + it("Checking leftRegion() method 2", () => { + let cons = new Connections(4); + + expect(cons.downRegion([0,0] )).toEqual([0,1]); + expect(cons.downRegion([1,2] )).toEqual(null); + expect(cons.downRegion([1,0] )).toEqual([1,1]); + expect(cons.downRegion([1,1] )).toEqual(null); + expect(cons.downRegion([2,0] )).toEqual(null); + expect(cons.downRegion([2,1] )).toEqual(null); + expect(cons.downRegion([2,-1] )).toEqual(null); + expect(cons.downRegion([1,-1] )).toEqual([1,0]); + expect(cons.downRegion([-1,-1])).toEqual(null); cons.destroy(); }); it('Checking getConnection() method', () => { const cons = new Connections(1); - expect(cons.getConnection([1,1]).sock).toEqual(null); + expect(cons.getConnection([1,1])).toEqual(null); expect(cons.getConnection([0,0]).sock).toEqual(null); - expect(cons.getConnection([2,2]).sock).toEqual(null); + expect(cons.getConnection([2,2])).toEqual(null); cons.destroy(); }); it('Checking setData() method', () => { const cons = new Connections(1); + cons.setData([0,0], 'active', true); + expect(cons.getConnection([0,0]).active).toEqual(true); + expect(cons.getConnection([0,0]).sock).toEqual(null); + expect(cons.getConnection([1,1])).toEqual(null); + expect(cons.getConnection([0,1])).toEqual(null); + expect(cons.getConnection([1,0])).toEqual(null); + expect(cons.getConnection([2,1])).toEqual(null); + expect(cons.getConnection([2,2])).toEqual(null); + expect(cons.getConnection([1,2])).toEqual(null); + + cons.setData([0,0], 'active', false); + expect(cons.getConnection([1,1])).toEqual(null); + expect(cons.getConnection([0,1])).toEqual(null); + expect(cons.getConnection([0,0]).active).toEqual(false); + expect(cons.getConnection([0,0]).sock).toEqual(null); + expect(cons.getConnection([1,0])).toEqual(null); + expect(cons.getConnection([2,1])).toEqual(null); + expect(cons.getConnection([2,2])).toEqual(null); + expect(cons.getConnection([1,2])).toEqual(null); + + cons.clearData([0,0]); + expect(cons.getConnection([1,1])).toEqual(null); + expect(cons.getConnection([0,1])).toEqual(null); + expect(cons.getConnection([0,0]).active).toEqual(undefined); + expect(cons.getConnection([0,0]).sock).toEqual(null); + expect(cons.getConnection([1,0])).toEqual(null); + expect(cons.getConnection([2,1])).toEqual(null); + expect(cons.getConnection([2,2])).toEqual(null); + expect(cons.getConnection([1,2])).toEqual(null); + + cons.destroy(); + }); + it('Checking setData() method 2', () => { + const cons = new Connections(9); + cons.setData([1,1], 'active', true); + expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,1]).active).toEqual(true); expect(cons.getConnection([0,1]).active).toEqual(undefined); - expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,0]).active).toEqual(undefined); expect(cons.getConnection([2,1]).active).toEqual(undefined); expect(cons.getConnection([2,2]).active).toEqual(undefined); expect(cons.getConnection([1,2]).active).toEqual(undefined); cons.setData([1,1], 'active', false); + expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,1]).active).toEqual(false); expect(cons.getConnection([0,1]).active).toEqual(undefined); - expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,0]).active).toEqual(undefined); expect(cons.getConnection([2,1]).active).toEqual(undefined); expect(cons.getConnection([2,2]).active).toEqual(undefined); expect(cons.getConnection([1,2]).active).toEqual(undefined); cons.clearData([1,1]); + expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,1]).active).toEqual(undefined); expect(cons.getConnection([0,1]).active).toEqual(undefined); - expect(cons.getConnection([0,0]).active).toEqual(undefined); expect(cons.getConnection([1,0]).active).toEqual(undefined); expect(cons.getConnection([2,1]).active).toEqual(undefined); expect(cons.getConnection([2,2]).active).toEqual(undefined); @@ -116,25 +229,25 @@ describe("server/src/server/Connections", () => { it('Checking clearData() method', () => { const cons = new Connections(1); - cons.setData([1,1], 'prop', true); - expect(cons.getConnection([1,1]).prop).toEqual(true); - cons.clearData([1,1]); - expect(cons.getConnection([1,1]).prop).toEqual(undefined); - cons.setData([1,1], 'prop', true); - cons.setData([1,1], 'prop', 1); - expect(cons.getConnection([1,1]).prop).toEqual(1); + cons.setData([0,0], 'prop', true); + expect(cons.getConnection([0,0]).prop).toEqual(true); + cons.clearData([0,0]); + expect(cons.getConnection([0,0]).prop).toEqual(undefined); + cons.setData([0,0], 'prop', true); + cons.setData([0,0], 'prop', 1); + expect(cons.getConnection([0,0]).prop).toEqual(1); cons.destroy(); }); it('Checking getFreeRegion() method', () => { const cons = new Connections(1); - expect(THelper.compare(cons.getFreeRegion(), [1,1])).toEqual(true); - expect(THelper.compare(cons.getFreeRegion(), [1,1])).toEqual(true); - cons.setData([1,1], 'sock', true); + expect(cons.getFreeRegion()).toEqual([0,0]); + expect(cons.getFreeRegion()).toEqual([0,0]); + cons.setData([0,0], 'sock', true); expect(cons.getFreeRegion()).toEqual(null); - cons.clearData([1,1]); - expect(THelper.compare(cons.getFreeRegion(), [1,1])).toEqual(true); + cons.clearData([0,0]); + expect(cons.getFreeRegion()).toEqual([0,0]); cons.destroy(); }); diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index caeffbe..8a2eca9 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -6,6 +6,7 @@ * * @author flatline */ +const _get = require('lodash/get'); const Helper = require('./../../../../common/src/Helper'); const TYPES = require('./../../../../common/src/net/Requests').TYPES; const Console = require('./../../share/Console'); @@ -128,10 +129,10 @@ class Api extends BaseApi { // // We should also send around active clients status to the current (sock) // - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.DOWN, !!conns.getConnection(conns.downRegion(activeRegion)).sock); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.LEFT, !!conns.getConnection(conns.leftRegion(activeRegion)).sock); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, !!conns.getConnection(conns.upRegion(activeRegion)).sock); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, !!conns.getConnection(conns.rightRegion(activeRegion)).sock); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.DOWN, !!conns.getConnection(_get(conns.downRegion(activeRegion), 'sock'))); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.LEFT, !!conns.getConnection(_get(conns.leftRegion(activeRegion), 'sock'))); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, !!conns.getConnection(_get(conns.upRegion(activeRegion), 'sock'))); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, !!conns.getConnection(_get(conns.rightRegion(activeRegion), 'sock'))); } /** @@ -142,10 +143,10 @@ class Api extends BaseApi { _activateAround(region, activate = true) { const server = this.parent; const conns = server.conns; - const upSock = conns.getConnection(conns.upRegion(region)).sock; - const rightSock = conns.getConnection(conns.rightRegion(region)).sock; - const downSock = conns.getConnection(conns.downRegion(region)).sock; - const leftSock = conns.getConnection(conns.leftRegion(region)).sock; + const upSock = _get(conns.getConnection(conns.upRegion(region)), 'sock'); + const rightSock = _get(conns.getConnection(conns.rightRegion(region)), 'sock'); + const downSock = _get(conns.getConnection(conns.downRegion(region)), 'sock'); + const leftSock = _get(conns.getConnection(conns.leftRegion(region)), 'sock'); upSock && server.request(upSock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.DOWN, activate); rightSock && server.request(rightSock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.LEFT, activate); From 76b6061ee5295714b018daf3b7a6fafa25354282 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 11 Dec 2017 23:46:19 +0200 Subject: [PATCH 025/291] working on distributed servers calculations #13 fixed tests #83 --- server/src/server/AroundServers.js | 13 ++++++++++++- server/src/server/Server.js | 10 +++++++++- server/src/server/plugins/Api.js | 6 ++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index a6056c4..069718f 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -19,6 +19,7 @@ const DIR = require('./../../../common/src/Directions').DIR; const NAMES = require('./../../../common/src/Directions').NAMES; const TYPES = require('./../../../common/src/net/Requests').TYPES; const AsyncParent = require('./../../../common/src/plugins/AsyncParent'); +const Console = require('./../share/Console'); const Client = require('./Client'); /** * {Array} Array of flipped directions. Is used for connecting with nearest @@ -78,6 +79,16 @@ class AroundServers { }); } + /** + * Returns direction by socket + * @param {WebSocket} sock + * @return {Number} Direction DIR.NO is also available + */ + getDirection(sock) { + const index = this._socks.indexOf(sock); + return index < 0 && DIR.NO || index; + } + setSocket(sock, dir) { this._socks[dir] = sock; } @@ -118,7 +129,7 @@ class AroundServers { return; } this._socks[dir] = client.socket; - Console.info(`Connected with '${dir}' server`); + Console.info(`Connected with '${NAMES[dir]}' server`); }); } } diff --git a/server/src/server/Server.js b/server/src/server/Server.js index fe5f9e0..beefbff 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -37,6 +37,8 @@ const Config = require('./../share/Config').Config; const Plugins = require('./Plugins'); const Console = require('./../share/Console'); const Connections = require('./Connections'); +const DIR = require('./../../../common/src/Directions').DIR; +const NAMES = require('./../../../common/src/Directions').NAMES; /** * {Number} Amount of base events. Is used to extend them by server related */ @@ -226,7 +228,13 @@ class Server extends Connection { sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); - Console.warn(`Client ${clientId} has disconnected by reason: ${this.closeReason}`); + Console.warn(`Client '${this._getClientId(clientId, sock)}' has disconnected by reason: ${this.closeReason}`); + } + + _getClientId(clientId, sock) { + if (!this.aroundServers) {return clientId} + const dir = this.aroundServers.getDirection(sock); + return dir === DIR.NO ? clientId : NAMES[dir]; } } diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 8a2eca9..34fe85c 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -13,7 +13,7 @@ const Console = require('./../../share/Console'); const Connections = require('./../Connections'); const DIR = require('./../../../../common/src/Directions').DIR; -const DIR_NAMES = require('./../../../../common/src/Directions').NAMES; +const NAMES = require('./../../../../common/src/Directions').NAMES; const BaseApi = require('./../../../../common/src/net/Api'); class Api extends BaseApi { constructor(parent) { @@ -59,7 +59,7 @@ class Api extends BaseApi { const org = JSON.parse(orgJson); const backRegion = Connections.toRegion(clientId); const backCon = this.parent.conns.getConnection(backRegion); - this.parent.request(backCon.sock, TYPES.RES_MOVE_ERR, x, y, dir, orgJson, `Region "${region}" on direction "${DIR_NAMES[dir]}" is not active`); + this.parent.request(backCon.sock, TYPES.RES_MOVE_ERR, x, y, dir, orgJson, `Region "${region}" on direction "${NAMES[dir]}" is not active`); Console.error(`Destination region ${region} is not active. Organism "${org.id}" will be sent back.`); } } @@ -94,6 +94,8 @@ class Api extends BaseApi { */ _setNearServer(reqId, dir) { this.parent.aroundServers.setSocket(this.sock, dir); + this.parent.response(this.sock, TYPES.RES_SET_NEAR_ACTIVE_OK, reqId); + Console.info(`'${NAMES[dir]}' server has connected`); } /** From bb2e897f7423dc7d512ad137f3ac7026d8be9972 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 12 Dec 2017 10:04:59 +0200 Subject: [PATCH 026/291] working on distributed servers calculations #13 --- server/src/server/AroundServers.js | 2 +- server/src/server/Server.js | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 069718f..d7cae10 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -90,7 +90,7 @@ class AroundServers { } setSocket(sock, dir) { - this._socks[dir] = sock; + dir !== DIR.NO && (this._socks[dir] = sock); } _createClients() { diff --git a/server/src/server/Server.js b/server/src/server/Server.js index beefbff..5a07f7b 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -223,18 +223,16 @@ class Server extends Connection { */ onClose(clientId, sock, event) { super.onClose(event); - const region = Connections.toRegion(clientId); - this.conns.clearData(region); + const servers = this.aroundServers; + const region = Connections.toRegion(clientId); + const dir = servers ? servers.getDirection(sock) : clientId; + + this.conns.clearData( region); sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); - Console.warn(`Client '${this._getClientId(clientId, sock)}' has disconnected by reason: ${this.closeReason}`); - } - - _getClientId(clientId, sock) { - if (!this.aroundServers) {return clientId} - const dir = this.aroundServers.getDirection(sock); - return dir === DIR.NO ? clientId : NAMES[dir]; + servers && servers.setSocket(sock, dir); + Console.warn(`Client '${dir !== DIR.NO ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); } } From 2624601726e9c056d1944a7b6822a929d4606a3b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 12 Dec 2017 16:41:27 +0200 Subject: [PATCH 027/291] first beta skeleton of all communication scenarios between clients and servers #13 --- .../src/manager/plugins/client/plugins/Api.js | 5 +- server/src/server/AroundServers.js | 34 +++- server/src/server/Connections.js | 4 + server/src/server/plugins/Api.js | 170 ++++++++++++++---- 4 files changed, 175 insertions(+), 38 deletions(-) diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 919d289..96203bd 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -14,7 +14,6 @@ class Api extends BaseApi { super(client); this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this); - this.api[TYPES.RES_MOVE_ERR] = this._stepIn.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setActive.bind(this); } @@ -30,12 +29,10 @@ class Api extends BaseApi { * @param {Number} y Current org Y position * @param {Number} dir Direction of moving * @param {String} orgJson Organism's serialized json - * @param {String|null} errMsg Error message * @api */ - _stepIn(reqId, x, y, dir, orgJson, errMsg = null) { + _stepIn(reqId, x, y, dir, orgJson) { this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson); - errMsg && Console.warn(errMsg); } /** diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index d7cae10..cb30c31 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -2,7 +2,7 @@ * This class stores logic of communication with nearest servers (up, right, * down and left), which are connected to current one. It keeps connections * to them and updates active status. There are two types of connection with - * servers ans saving their sockets: + * servers and saving their sockets: * 1. create local clients and connect them to remote servers * 2. catch input connection from remote client * @@ -19,6 +19,7 @@ const DIR = require('./../../../common/src/Directions').DIR; const NAMES = require('./../../../common/src/Directions').NAMES; const TYPES = require('./../../../common/src/net/Requests').TYPES; const AsyncParent = require('./../../../common/src/plugins/AsyncParent'); +const Observer = require('./../../../common/src/Observer'); const Console = require('./../share/Console'); const Client = require('./Client'); /** @@ -26,10 +27,22 @@ const Client = require('./Client'); * servers: left -> right, up -> down, right -> left, down -> up */ const FLIP_DIR = [DIR.DOWN, DIR.LEFT, DIR.UP, DIR.RIGHT]; +/** + * Events of this class + */ +const OPEN = 0; +const CLOSE = 1; +const EVENTS = { + OPEN, + CLOSE +}; // TODO: later here should be auto connect mechanism for this._clients -class AroundServers { +class AroundServers extends Observer { constructor(parent) { + super(Object.keys(EVENTS).length); + + this.EVENTS = EVENTS; /** * {Connection} Connection instance of current Client or Server */ @@ -76,6 +89,7 @@ class AroundServers { this._clients.forEach(c => c.destroy()); this._clients = null; this._async.destroy(done); + super.destroy(); }); } @@ -89,6 +103,14 @@ class AroundServers { return index < 0 && DIR.NO || index; } + hasSocket(dir) { + return !!this._socks[dir]; + } + + getSocket(dir) { + return this._socks[dir]; + } + setSocket(sock, dir) { dir !== DIR.NO && (this._socks[dir] = sock); } @@ -111,7 +133,7 @@ class AroundServers { clients.forEach((c, i) => { c.on(c.EVENTS.OPEN, this._onOpen.bind(this, c, i)); - c.on(c.EVENTS.CLOSE, () => socks[i] = null); + c.on(c.EVENTS.CLOSE, () => this._onClose.bind(this, i)); }); } /** @@ -129,9 +151,15 @@ class AroundServers { return; } this._socks[dir] = client.socket; + this.fire(OPEN, dir); Console.info(`Connected with '${NAMES[dir]}' server`); }); } + + _onClose(dir) { + this._socks[dir] = null; + this.fire(CLOSE, dir); + } } module.exports = AroundServers; \ No newline at end of file diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index f3b3fa1..dd65b1f 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -52,6 +52,10 @@ class Connections { } } + get side() { + return this._side; + } + destroy() { this.conns = null; this._side = null; diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 34fe85c..43e5883 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -18,24 +18,38 @@ const BaseApi = require('./../../../../common/src/net/Api'); class Api extends BaseApi { constructor(parent) { super(parent); + const servers = parent.aroundServers; + this.api[TYPES.REQ_MOVE_ORG] = this._moveOrg.bind(this); this.api[TYPES.REQ_GET_ID] = this._getId.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setNearServer.bind(this); - this._onCloseCb = this._onClose.bind(this); + this._onCloseCb = this._onClose.bind(this); + this._onServerOpenCb = this._onServerOpen.bind(this); + this._onServerCloseCb = this._onServerClose.bind(this); Helper.override(parent, 'onClose', this._onCloseCb); + servers && servers.on(servers.EVENTS.OPEN, this._onServerOpenCb); + servers && servers.on(servers.EVENTS.CLOSE, this._onServerCloseCb); } destroy() { + const servers = parent.aroundServers; + Helper.unoverride(this.parent, 'onClose', this._onCloseCb); - this._onCloseCb = null; + servers && servers.off(servers.EVENTS.CLOSE, this._onServerCloseCb); + servers && servers.off(servers.EVENTS.OPEN, this._onServerOpenCb); + + this._onCloseCb = null; + this._onServerCloseCb = null; + this._onServerOpenCb = null; super.destroy(); } /** - * Moves organism from one client to another + * Moves organism from one client to another or to nearest server if + * it's connected to current one * @param {Number} reqId Unique request id. Needed for response * @param {String} clientId Unique client id * @param {Number} x Current org X position @@ -45,22 +59,14 @@ class Api extends BaseApi { * @api */ _moveOrg(reqId, clientId, x, y, dir, orgJson) { - const region = Connections.toRegion(clientId); - - if (dir === DIR.UP) {region[1]--} - else if (dir === DIR.RIGHT) {region[0]++} - else if (dir === DIR.DOWN) {region[1]++} - else if (dir === DIR.LEFT) {region[0]--} + const reg = Connections.toRegion(clientId); + const side = this.parent.conns.side - 1; - const con = this.parent.conns.getConnection(region); - if (con.active) { - this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); + if (dir === DIR.UP && reg[1] > 0 || dir === DIR.RIGHT && reg[0] < side || + dir === DIR.DOWN && reg[1] < side || dir === DIR.LEFT && reg[0] > 0) { + this._moveToClient(clientId, x, y, dir, orgJson); } else { - const org = JSON.parse(orgJson); - const backRegion = Connections.toRegion(clientId); - const backCon = this.parent.conns.getConnection(backRegion); - this.parent.request(backCon.sock, TYPES.RES_MOVE_ERR, x, y, dir, orgJson, `Region "${region}" on direction "${NAMES[dir]}" is not active`); - Console.error(`Destination region ${region} is not active. Organism "${org.id}" will be sent back.`); + this._moveToServer(clientId, x, y, dir, orgJson); } } @@ -98,6 +104,58 @@ class Api extends BaseApi { Console.info(`'${NAMES[dir]}' server has connected`); } + /** + * Moves organism's json to nearest client depending on dir parameter + * @param {String} clientId Unique client id + * @param {Number} x Organism x coordinate + * @param {Number} y Organism y coordinate + * @param {Number} dir Moving direction + * @param {String} orgJson Organism's serialized json + */ + _moveToClient(clientId, x, y, dir, orgJson) { + const region = Connections.toRegion(clientId); + + if (dir === DIR.UP) {region[1]--} + else if (dir === DIR.RIGHT) {region[0]++} + else if (dir === DIR.DOWN) {region[1]++} + else if (dir === DIR.LEFT) {region[0]--} + + const con = this.parent.conns.getConnection(region); + if (con.active) { + this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); + } else { + // TODO: possibly slow code - parse() do we really need this line? + const org = JSON.parse(orgJson); + const backRegion = Connections.toRegion(clientId); + const backCon = this.parent.conns.getConnection(backRegion); + this.parent.request(backCon.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); + Console.info(`Destination region ${region} is not active. Organism "${org.id}" will be sent back.`); + } + } + + /** + * Moves organism's json to nearest server depending on dir parameter + * @param {String} clientId Unique client id + * @param {Number} x Organism x coordinate + * @param {Number} y Organism y coordinate + * @param {Number} dir Moving direction + * @param {String} orgJson Organism's serialized json + */ + _moveToServer(clientId, x, y, dir, orgJson) { + const region = Connections.toRegion(clientId); + + const sock = this.parent.aroundServers.getSocket(dir); + if (sock) { + this.parent.request(sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); + } else { + // TODO: possibly slow code - parse() do we really need this line? + const org = JSON.parse(orgJson); + const backCon = this.parent.conns.getConnection(region); + this.parent.request(backCon.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); + Console.error(`Destination server ${NAMES[dir]} is not active. Organism "${org.id}" will be sent back.`); + } + } + /** * Sets client active. It means, that sibling active client may * transfer it's organisms to this client @@ -120,21 +178,25 @@ class Api extends BaseApi { * @param {Array} activeRegion Region of activated client */ _activateAll(activeRegion) { - const server = this.parent; - const conns = server.conns; - const sock = server.conns.getConnection(activeRegion).sock; - // - // We have to send activate message every nearest client to - // current lying on activeRegion - // this._activateAround(activeRegion); - // - // We should also send around active clients status to the current (sock) - // - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.DOWN, !!conns.getConnection(_get(conns.downRegion(activeRegion), 'sock'))); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.LEFT, !!conns.getConnection(_get(conns.leftRegion(activeRegion), 'sock'))); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, !!conns.getConnection(_get(conns.upRegion(activeRegion), 'sock'))); - server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, !!conns.getConnection(_get(conns.rightRegion(activeRegion), 'sock'))); + this._activateCentral(activeRegion); + } + + _activateCentral(region) { + const server = this.parent; + const conns = server.conns; + const sock = server.conns.getConnection(region).sock; + const servers = this.parent.aroundServers; + const side = conns.side - 1; + const activeUp = !!conns.getConnection(_get(conns.upRegion (region), 'sock')) || region[1] === 0 && servers.hasSocket(DIR.UP); + const activeRight = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[0] === side && servers.hasSocket(DIR.RIGHT); + const activeDown = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[1] === side && servers.hasSocket(DIR.DOWN); + const activeLeft = !!conns.getConnection(_get(conns.leftRegion(region), 'sock')) || region[0] === 0 && servers.hasSocket(DIR.LEFT); + + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, activeUp); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, activeRight); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.DOWN, activeDown); + server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.LEFT, activeLeft); } /** @@ -165,6 +227,52 @@ class Api extends BaseApi { _onClose(clientId) { this._activateAround(Connections.toRegion(clientId), false); } + + /** + * Handler of opening connection with near server. dir parameter points to + * the direction of near server. If new near server appears, we have to notify + * near clients about it. + * @param {Number} dir Direction of server + */ + _onServerOpen(dir) { + this._updateConnections(dir, true); + } + + /** + * Handler of closing connection with near server. dir parameter points to + * the direction of near server. If near server disappears, we have to notify + * near clients about it. + * @param {Number} dir Direction of server + */ + _onServerClose(dir) { + this._updateConnections(dir, false); + } + + _updateConnections(dir, open) { + const server = this.parent; + const conns = server.conns; + const side = conns.side; + let region; + let line; + let sock; + let offs; + + if (dir === DIR.UP || dir === DIR.DOWN) { + line = dir === DIR.UP ? 0 : side - 1; + region = [0, line]; + offs = 0; + } else { + line = dir === DIR.LEFT ? 0 : side - 1; + region = [line, 0]; + offs = 1; + } + + for (let i = 0; i < side; i++) { + region[offs] = i; + sock = conns.getConnection(region).sock; + sock && server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, dir, open); + } + } } module.exports = Api; \ No newline at end of file From 45ece3be37d8799d42975a5b6ee40314c1483870 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 12 Dec 2017 16:45:32 +0200 Subject: [PATCH 028/291] fixed tests #83 --- server/src/server/plugins/Api.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 43e5883..760008d 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -34,7 +34,7 @@ class Api extends BaseApi { } destroy() { - const servers = parent.aroundServers; + const servers = this.parent.aroundServers; Helper.unoverride(this.parent, 'onClose', this._onCloseCb); servers && servers.off(servers.EVENTS.CLOSE, this._onServerCloseCb); @@ -188,10 +188,10 @@ class Api extends BaseApi { const sock = server.conns.getConnection(region).sock; const servers = this.parent.aroundServers; const side = conns.side - 1; - const activeUp = !!conns.getConnection(_get(conns.upRegion (region), 'sock')) || region[1] === 0 && servers.hasSocket(DIR.UP); - const activeRight = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[0] === side && servers.hasSocket(DIR.RIGHT); - const activeDown = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[1] === side && servers.hasSocket(DIR.DOWN); - const activeLeft = !!conns.getConnection(_get(conns.leftRegion(region), 'sock')) || region[0] === 0 && servers.hasSocket(DIR.LEFT); + const activeUp = !!conns.getConnection(_get(conns.upRegion (region), 'sock')) || region[1] === 0 && servers && servers.hasSocket(DIR.UP); + const activeRight = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[0] === side && servers && servers.hasSocket(DIR.RIGHT); + const activeDown = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[1] === side && servers && servers.hasSocket(DIR.DOWN); + const activeLeft = !!conns.getConnection(_get(conns.leftRegion(region), 'sock')) || region[0] === 0 && servers && servers.hasSocket(DIR.LEFT); server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, activeUp); server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, activeRight); From 226910fb630e17bf02ac625b79efdfbbfd335fba Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 12 Dec 2017 17:12:30 +0200 Subject: [PATCH 029/291] fixed small issues related to servers console connection messages #13 --- server/src/server/AroundServers.js | 4 ++-- server/src/server/Client.js | 14 +++++++++----- server/src/server/plugins/Api.js | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index cb30c31..a69bb1e 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -147,12 +147,12 @@ class AroundServers extends Observer { _onOpen(client, dir) { client.request(client.socket, TYPES.REQ_SET_NEAR_ACTIVE, FLIP_DIR[dir], (type) => { if (type !== TYPES.RES_SET_NEAR_ACTIVE_OK) { - Console.error(`Unable to connect to '${NAMES[dir]}' server. Response type: ${type}`); + Console.error(`Unable update active status on '${NAMES[dir]}' server. Response type: ${type}`); return; } this._socks[dir] = client.socket; this.fire(OPEN, dir); - Console.info(`Connected with '${NAMES[dir]}' server`); + Console.info(`Active status of '${NAMES[dir]}' server has updated`); }); } diff --git a/server/src/server/Client.js b/server/src/server/Client.js index 40b33ca..7caeafa 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -33,12 +33,12 @@ class Client extends BaseClient { /** * Is called if error occurred - * @param {String} msg + * @param {Object} event Error event object * @override */ - onError(msg) { - super.onError(msg); - Console.error(`'${NAMES[this._dir]}' server error: ${msg} on ${this.host}:${this.port}`); + onError(event) { + super.onError(event); + Console.error(`'${NAMES[this._dir]}' server error: ${event.message} on ${this.host}:${this.port}`); } /** @@ -48,8 +48,12 @@ class Client extends BaseClient { * @override */ onClose(event) { + const active = this.active; super.onClose(event); - Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: ${this.closeReason} on ${this.host}:${this.port}`); + // + // We have to show message only if we had been active for some time + // + active && Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: ${this.closeReason} on ${this.host}:${this.port}`); } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 760008d..a5cf751 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -124,7 +124,7 @@ class Api extends BaseApi { if (con.active) { this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); } else { - // TODO: possibly slow code - parse() do we really need this line? + // TODO: possibly slow code - parse() do we really need this id? const org = JSON.parse(orgJson); const backRegion = Connections.toRegion(clientId); const backCon = this.parent.conns.getConnection(backRegion); @@ -148,7 +148,7 @@ class Api extends BaseApi { if (sock) { this.parent.request(sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); } else { - // TODO: possibly slow code - parse() do we really need this line? + // TODO: possibly slow code - parse() do we really need this id? const org = JSON.parse(orgJson); const backCon = this.parent.conns.getConnection(region); this.parent.request(backCon.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); From a76ae4dff57db46d26c3d4b932518b37ba938fb5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 13 Dec 2017 23:25:33 +0200 Subject: [PATCH 030/291] fitness function now is more precise, because organism changes are calculated more accurate --- .../src/manager/plugins/organisms/Mutator.js | 144 +++++++++--------- .../manager/plugins/organisms/Organisms.js | 4 +- client/src/vm/Num.js | 11 +- client/src/vm/VM.js | 9 +- server/src/server/plugins/Api.js | 12 +- 5 files changed, 97 insertions(+), 83 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index e251130..19fab12 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -17,75 +17,24 @@ const Num = require('./../../../vm/Num'); const VAR_BITS_OFFS = Num.VAR_BITS_OFFS - 1; const VARS = Num.VARS; const MAX_VAR = Num.MAX_VAR; +const MAX_BITS = Num.MAX_BITS; +const BITS_PER_VAR = Num.BITS_PER_VAR; class Mutator { - constructor(manager) { - this._manager = manager; - this._MUTATION_TYPES = [ - this._onAdd, - this._onChange, - this._onDel, - this._onSmallChange, - this._onClone, - this._onCopy, - this._onPeriod, - this._onAmount, - this._onProbs, - this._onCloneEnergyPercent - ]; - - manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); - manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); - } - - destroy() { - this._manager = null; - this._MUTATION_TYPES = null; - } - - _onOrganism(org) { - if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && org.mutationPeriod > 0 && org.alive) { - this._mutate(org, false); - } - } - - _onCloneOrg(parent, child) { - if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0) {this._mutate(child)} - } - - _mutate(org, clone = true) { - const jsvm = org.jsvm; - const probIndex = Helper.probIndex; - const mTypes = this._MUTATION_TYPES; - const maxSize = OConfig.codeMaxSize; - let mutations = Math.round(jsvm.size * (clone ? org.cloneMutationPercent : org.mutationPercent)) || 1; - let type; - - for (let i = 0; i < mutations; i++) { - if (jsvm.size > maxSize) { - mutations = i; - break; - } - type = jsvm.size < 1 ? 0 : probIndex(org.mutationProbs); - mTypes[type](org); - } - org.changes += mutations; - this._manager.fire(EVENTS.MUTATIONS, org, mutations, clone); - - return mutations; - } - - _onAdd(org) { - org.jsvm.size <= OConfig.codeMaxSize && org.jsvm.insertLine(); + static _onAdd(org) { + org.jsvm.insertLine(); + org.changes += MAX_BITS; } - _onChange(org) { + static _onChange(org) { const jsvm = org.jsvm; jsvm.updateLine(Helper.rand(jsvm.size), Num.get()); + org.changes += MAX_BITS; } - _onDel(org) { + static _onDel(org) { org.jsvm.removeLine(); + org.changes += MAX_BITS; } /** @@ -93,7 +42,7 @@ class Mutator { * @param {Organism} org * @private */ - _onSmallChange(org) { + static _onSmallChange(org) { const rand = Helper.rand; const jsvm = org.jsvm; const index = rand(jsvm.size); @@ -101,36 +50,95 @@ class Mutator { if (rnd === 0) { jsvm.updateLine(index, Num.setOperator(jsvm.getLine(index), rand(jsvm.operators.operators.length))); + org.changes += MAX_BITS; } else if (rnd === 1) { jsvm.updateLine(index, Num.setVar(jsvm.getLine(index), rand(VARS), rand(MAX_VAR))); + org.changes += BITS_PER_VAR; } else { // toggle specified bit jsvm.updateLine(index, jsvm.getLine(index) ^ (1 << rand(VAR_BITS_OFFS))); + org.changes++; } } - _onClone(org) { + static _onClone(org) { org.cloneMutationPercent = Math.random(); + org.changes++; } - _onCopy(org) { - org.jsvm.copyLines(); + static _onCopy(org) { + org.changes += (org.jsvm.copyLines() * MAX_BITS); + } - _onPeriod(org) { + static _onPeriod(org) { org.mutationPeriod = Helper.rand(OConfig.ORG_MAX_MUTATION_PERIOD); + org.changes++; } - _onAmount(org) { + static _onAmount(org) { org.mutationPercent = Math.random(); + org.changes++; } - _onProbs(org) { + static _onProbs(org) { org.mutationProbs[Helper.rand(org.mutationProbs.length)] = Helper.rand(OConfig.orgMutationProbsMaxValue) || 1; + org.changes++; } - _onCloneEnergyPercent(org) { + static _onCloneEnergyPercent(org) { org.cloneEnergyPercent = Math.random(); + org.changes++; + } + + constructor(manager) { + this._manager = manager; + this._MUTATION_TYPES = [ + Mutator._onAdd, + Mutator._onChange, + Mutator._onDel, + Mutator._onSmallChange, + Mutator._onClone, + Mutator._onCopy, + Mutator._onPeriod, + Mutator._onAmount, + Mutator._onProbs, + Mutator._onCloneEnergyPercent + ]; + + manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); + manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); + } + + destroy() { + this._manager = null; + this._MUTATION_TYPES = null; + } + + _onOrganism(org) { + if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && org.mutationPeriod > 0 && org.alive) { + this._mutate(org, false); + } + } + + _onCloneOrg(parent, child) { + if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0) {this._mutate(child)} + } + + _mutate(org, clone = true) { + const jsvm = org.jsvm; + const probIndex = Helper.probIndex; + const mTypes = this._MUTATION_TYPES; + const maxSize = OConfig.codeMaxSize; + let mutations = Math.round(jsvm.size * (clone ? org.cloneMutationPercent : org.mutationPercent)) || 1; + let type; + + for (let i = 0; i < mutations; i++) { + if (jsvm.size > maxSize) {mutations = i; break} + type = jsvm.size < 1 ? 0 : probIndex(org.mutationProbs); + mTypes[type](org); + } + this._manager.fire(EVENTS.MUTATIONS, org, mutations, clone); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 25e52d6..d14b74b 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -14,8 +14,10 @@ const Console = require('./../../../../src/share/Console'); const EVENTS = require('./../../../../src/share/Events').EVENTS; const Backup = require('./../backup/Backup'); const Mutator = require('./Mutator'); +const Num = require('./../../../vm/Num'); const RAND_OFFS = 4; +const MAX_BITS = Num.MAX_BITS; // TODO: inherit this class from Configurable class Organisms extends Configurable { @@ -263,7 +265,7 @@ class Organisms extends Configurable { let child = orgs.last.val; if (child.alive && looser.alive) { - child.changes += child.jsvm.crossover(looser.jsvm); + child.changes += (child.jsvm.crossover(looser.jsvm) * MAX_BITS); if (orgs.size >= OConfig.orgMaxOrgs) {looser.destroy()} } } diff --git a/client/src/vm/Num.js b/client/src/vm/Num.js index e6b7dc4..9637b62 100644 --- a/client/src/vm/Num.js +++ b/client/src/vm/Num.js @@ -4,24 +4,25 @@ * @author flatline */ const Helper = require('./../../../common/src/Helper'); -const Config = require('./../../src/share/Config').Config; const OConfig = require('./../manager/plugins/organisms/Config'); +const MAX_BITS = 32; const BITS_PER_VAR = OConfig.codeBitsPerVar; const BITS_PER_OPERATOR = OConfig.codeBitsPerOperator; const NO_OPERATOR_MASK = 0xffffffff >>> BITS_PER_OPERATOR; const BITS_OF_TWO_VARS = BITS_PER_VAR * 2; -const BITS_OF_FIRST_VAR = 32 - BITS_PER_VAR; +const BITS_OF_FIRST_VAR = MAX_BITS - BITS_PER_VAR; const MAX_VAR = 1 << BITS_PER_VAR; const MAX_OPERATOR = 1 << BITS_PER_OPERATOR; -const VAR_BITS_OFFS = 32 - BITS_PER_OPERATOR; +const VAR_BITS_OFFS = MAX_BITS - BITS_PER_OPERATOR; const BITS_WITHOUT_2_VARS = 1 << (VAR_BITS_OFFS - BITS_PER_VAR * 2); class Num { + static get MAX_BITS() {return MAX_BITS} static get VAR_BITS_OFFS() {return VAR_BITS_OFFS} static get BITS_PER_VAR() {return BITS_PER_VAR} static get BITS_PER_OPERATOR() {return BITS_PER_OPERATOR} - static get VARS() {return (32 - BITS_PER_OPERATOR) / BITS_PER_VAR} + static get VARS() {return (MAX_BITS - BITS_PER_OPERATOR) / BITS_PER_VAR} static get MAX_VAR() {return MAX_VAR} static get BITS_OF_TWO_VARS() {return BITS_OF_TWO_VARS} static get MAX_OPERATOR() {return MAX_OPERATOR} @@ -81,7 +82,7 @@ class Num { * @return {Number} Cut bits (number) */ static getBits(num, start, len) { - return num << start >>> (32 - len); + return num << start >>> (MAX_BITS - len); } } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 0fb5921..10eed23 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -182,6 +182,7 @@ class JSVM extends Observer { /** * Takes few lines from itself and makes a copy of them. After that inserts * them before or after copied part. All positions are random + * @return {Number} Amount of added/copied lines */ copyLines() { const rand = Helper.rand; @@ -194,21 +195,23 @@ class JSVM extends Observer { // for amount of parameters and we shouldn't exceed it // if (end - start > MAX_STACK_SIZE) { - return; + return 0; } // // Organism size should be less them codeMaxSize // - if (code.length + end - start >= OConfig.codeMaxSize) {return} + if (code.length + end - start >= OConfig.codeMaxSize) {return 0} // // We may insert copied piece before "start" (0) or after "end" (1) // if (rand(2) === 0) { code.splice(rand(start), 0, ...code.slice(start, end)); - return; + return end - start; } code.splice(end + rand(codeLen - end + 1), 0, ...code.slice(start, end)); + + return end - start; } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index a5cf751..c06ac35 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -20,9 +20,9 @@ class Api extends BaseApi { super(parent); const servers = parent.aroundServers; - this.api[TYPES.REQ_MOVE_ORG] = this._moveOrg.bind(this); - this.api[TYPES.REQ_GET_ID] = this._getId.bind(this); - this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setNearServer.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrg.bind(this); + this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); + this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); this._onCloseCb = this._onClose.bind(this); this._onServerOpenCb = this._onServerOpen.bind(this); @@ -58,7 +58,7 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _moveOrg(reqId, clientId, x, y, dir, orgJson) { + _onMoveOrg(reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const side = this.parent.conns.side - 1; @@ -75,7 +75,7 @@ class Api extends BaseApi { * @param {Number} reqId Unique request id. Needed for response * @api */ - _getId(reqId) { + _onGetId(reqId) { const sock = this.sock; const region = this.parent.conns.getFreeRegion(); const clientId = Connections.toId(region); @@ -98,7 +98,7 @@ class Api extends BaseApi { * @param {Number} dir Direction of incoming nearest server * @api */ - _setNearServer(reqId, dir) { + _onSetNearServer(reqId, dir) { this.parent.aroundServers.setSocket(this.sock, dir); this.parent.response(this.sock, TYPES.RES_SET_NEAR_ACTIVE_OK, reqId); Console.info(`'${NAMES[dir]}' server has connected`); From 02627db473da6b802dac9e6590e3677bb701695d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 13 Dec 2017 23:40:23 +0200 Subject: [PATCH 031/291] found perfect hack, how to increase running speed: set Config.codeIterationsPerOnce to 300 --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/share/Config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 17c8ab5..c2b0244 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 50, + codeIterationsPerOnce: 300, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 59f14fd..7db0e53 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... From 93f0765086da8adfe8fe2310616861192899f5a4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 13 Dec 2017 23:45:16 +0200 Subject: [PATCH 032/291] tuning clone part of config --- client/src/manager/plugins/organisms/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index c2b0244..844b028 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -54,7 +54,7 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 100, + orgClonePeriod: 10, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off From a9c121247cc5dad9491fd5de34719ec8d2b96f2c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 14 Dec 2017 00:38:43 +0200 Subject: [PATCH 033/291] fixed one scenario of distributed servers #13 --- server/src/server/AroundServers.js | 4 +--- server/src/server/Client.js | 2 +- server/src/server/plugins/Api.js | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index a69bb1e..4b63aae 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -129,11 +129,9 @@ class AroundServers extends Observer { } _addHandlers(clients) { - const socks = this._socks; - clients.forEach((c, i) => { c.on(c.EVENTS.OPEN, this._onOpen.bind(this, c, i)); - c.on(c.EVENTS.CLOSE, () => this._onClose.bind(this, i)); + c.on(c.EVENTS.CLOSE, this._onClose.bind(this, i)); }); } /** diff --git a/server/src/server/Client.js b/server/src/server/Client.js index 7caeafa..6dda83a 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -53,7 +53,7 @@ class Client extends BaseClient { // // We have to show message only if we had been active for some time // - active && Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: ${this.closeReason} on ${this.host}:${this.port}`); + active && Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: '${this.closeReason}' on ${this.host}:${this.port}`); } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index c06ac35..3779a3a 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -101,6 +101,7 @@ class Api extends BaseApi { _onSetNearServer(reqId, dir) { this.parent.aroundServers.setSocket(this.sock, dir); this.parent.response(this.sock, TYPES.RES_SET_NEAR_ACTIVE_OK, reqId); + this._onServerOpen(dir); Console.info(`'${NAMES[dir]}' server has connected`); } @@ -222,10 +223,19 @@ class Api extends BaseApi { * On connection close with one of the client we have to update active * state for nearest clients/Managers * @param {String} clientId Deactivated client id + * @param {WebSocket} sock * @private */ - _onClose(clientId) { - this._activateAround(Connections.toRegion(clientId), false); + _onClose(clientId, sock) { + const servers = this.parent.aroundServers; + const dir = servers ? servers.getDirection(sock) : clientId; + + if (dir === DIR.NO) { + this._activateAround(Connections.toRegion(clientId), false); + return; + } + + this._onServerClose(dir); } /** From 08113d64807ec6aed5114813626bf5fefc7c7639 Mon Sep 17 00:00:00 2001 From: Taras Date: Thu, 14 Dec 2017 01:12:00 +0200 Subject: [PATCH 034/291] Update README.md A minor typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 216ae21..a8fa05f 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,4 @@ Note: to improve speed, type `man.api.visualize(false)` in Chrome's devtool console during application run ___ -P.S. If you `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! \ No newline at end of file +P.S. If you are a `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! From 96e5e8208dffca1bf3c978b83ad4d304fadc9635 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 15 Dec 2017 01:02:14 +0200 Subject: [PATCH 035/291] fixed many small issues related to server to server communication #13 --- client/src/share/Config.js | 2 +- common/src/net/Requests.js | 15 +++--- server/src/server/AroundServers.js | 11 +++-- server/src/server/Client.js | 21 ++++++++- server/src/server/Connections.js | 21 ++++++++- server/src/server/Server.js | 13 +++--- server/src/server/plugins/Api.js | 74 +++++++++++++++++------------- server/src/share/Config.js | 8 ++-- 8 files changed, 107 insertions(+), 58 deletions(-) diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 7db0e53..cbe7140 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -97,7 +97,7 @@ ClientConfig.init({ /** * {Number} Port number for connecting with server */ - serverPort: 8099, + serverPort: 8100, /** * {String} Host for connecting with server */ diff --git a/common/src/net/Requests.js b/common/src/net/Requests.js index 6da2c7d..433c8d6 100644 --- a/common/src/net/Requests.js +++ b/common/src/net/Requests.js @@ -17,16 +17,17 @@ const TYPES = { // // Requests section // - REQ_MOVE_ORG : 0, // Organism moves from one world(manager) to another(sibling) - REQ_SET_NEAR_ACTIVE : 1, // Other (near) server wants to connect with current one - REQ_GET_ID : 2, // Client wants obtain it's unique id from server + REQ_MOVE_ORG : 0, // Organism moves from one world(manager) to another(sibling) + REQ_SET_NEAR_ACTIVE : 1, // Other (near) server wants to connect with current one + REQ_GET_ID : 2, // Client wants obtain it's unique id from server + REQ_MOVE_ORG_FROM_SERVER: 3, // Organism came from near server // // Responses section // - RES_MOVE_ERR : 1000, - RES_INVALID_TYPE : 1001, - RES_GET_ID_OK : 1002, - RES_SET_NEAR_ACTIVE_OK: 1003 + RES_MOVE_ERR : 1000, + RES_INVALID_TYPE : 1001, + RES_GET_ID_OK : 1002, + RES_SET_NEAR_ACTIVE_OK : 1003 }; module.exports = {TYPES, MASKS}; \ No newline at end of file diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 4b63aae..9ae3e99 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -116,13 +116,14 @@ class AroundServers extends Observer { } _createClients() { - const cfg = this._parent.cfg; + const parent = this._parent; + const cfg = parent.cfg; const clients = this._clients; - clients[DIR.UP] = new Client(DIR.UP, cfg.upHost, cfg.upPort, true); - clients[DIR.RIGHT] = new Client(DIR.RIGHT, cfg.rightHost, cfg.rightPort, true); - clients[DIR.DOWN] = new Client(DIR.DOWN, cfg.downHost, cfg.downPort, true); - clients[DIR.LEFT] = new Client(DIR.LEFT, cfg.leftHost, cfg.leftPort, true); + clients[DIR.UP] = new Client(parent, DIR.UP, cfg.upHost, cfg.upPort, true); + clients[DIR.RIGHT] = new Client(parent, DIR.RIGHT, cfg.rightHost, cfg.rightPort, true); + clients[DIR.DOWN] = new Client(parent, DIR.DOWN, cfg.downHost, cfg.downPort, true); + clients[DIR.LEFT] = new Client(parent, DIR.LEFT, cfg.leftHost, cfg.leftPort, true); this._addHandlers(clients); this._async = new AsyncParent(this, {classes: clients, isBrowser: false}); diff --git a/server/src/server/Client.js b/server/src/server/Client.js index 6dda83a..0e326bc 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -15,9 +15,14 @@ const PLUGINS = [ ]; class Client extends BaseClient { - constructor(dir, host, port) { + constructor(server, dir, host, port) { super(host, port, true); - this._dir = dir; + /** + * {Server} Parent server created current client for communication + * with near servers. + */ + this._server = server; + this._dir = dir; // // Plugins should be created at the end of constructor to // have an ability to access this class public fields @@ -41,6 +46,18 @@ class Client extends BaseClient { Console.error(`'${NAMES[this._dir]}' server error: ${event.message} on ${this.host}:${this.port}`); } + /** + * Is called every time if near server sends us a request. This is + * a bridge between near server and current server + * @param {WebSocket} sock Socket, received the message + * @param {Event} event Message event. Data is in 'data' property + * @override + */ + onMessage(sock, event) { + super.onMessage(sock, event); + this._server.onMessage(sock, event); + } + /** * Is called on connection close with server. Close reason will be in * this.closeReason field after calling super.onClose() method diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index dd65b1f..c0ad245 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -8,6 +8,7 @@ * * @author flatline */ +const DIR = require('./../../../common/src/Directions').DIR; /** * {String} Separator string, which separates id parts. Like * 'X' + ID_SEPARATOR + 'X' @@ -31,7 +32,7 @@ class Connections { * @returns {Array} Array of numbers (region) */ static toRegion(id) { - return id.split(ID_SEPARATOR).map(Number); + return id && id.split(ID_SEPARATOR).map(Number); } constructor(amount) { @@ -101,6 +102,24 @@ class Connections { return this._validRegion(region) && region || null; } + /** + * Returns opposite region. It means the region on the diagonally + * other side related to specified. up -> down, right -> left,... + * @param {Array} region + * @param {Number} dir Direction + * @return {Array} Opposite region + */ + oppositeRegion(region, dir) { + const side = this._side - 1; + + if (dir === DIR.UP) {region[1] = side; return region} + if (dir === DIR.RIGHT) {region[0] = 0; return region} + if (dir === DIR.DOWN) {region[1] = 0; return region} + if (dir === DIR.LEFT) {region[0] = side; return region} + + return region; + } + /** * Returns connection object by region * @param {Array} region Region to get diff --git a/server/src/server/Server.js b/server/src/server/Server.js index 5a07f7b..2f3646c 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -200,7 +200,7 @@ class Server extends Connection { onConnect(sock) { const region = this.conns.getFreeRegion(); const clientId = Connections.toId(region); - if (region === null) { + if (region === null && this._server.clients.length > Config.maxConnections + 4) { // 4 extra connections for near servers sock.terminate(); this.fire(OVERFLOW, sock); Console.warn('This server is overloaded by clients. Try another server to connect.'); @@ -223,16 +223,17 @@ class Server extends Connection { */ onClose(clientId, sock, event) { super.onClose(event); - const servers = this.aroundServers; - const region = Connections.toRegion(clientId); - const dir = servers ? servers.getDirection(sock) : clientId; + const servers = this.aroundServers; + const region = Connections.toRegion(clientId); + const dir = servers ? servers.getDirection(sock) : clientId; + const isServer = dir !== clientId; - this.conns.clearData( region); + !isServer && this.conns.clearData(region); sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); servers && servers.setSocket(sock, dir); - Console.warn(`Client '${dir !== DIR.NO ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); + Console.warn(`Client '${isServer ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); } } diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 3779a3a..c57613f 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -20,9 +20,10 @@ class Api extends BaseApi { super(parent); const servers = parent.aroundServers; - this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrg.bind(this); - this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); - this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrg.bind(this); + this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this); + this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); + this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); this._onCloseCb = this._onClose.bind(this); this._onServerOpenCb = this._onServerOpen.bind(this); @@ -47,6 +48,22 @@ class Api extends BaseApi { super.destroy(); } + /** + * Moves organism from near server to current server + * @param {Number} reqId Unique request id. Needed for response + * @param {String} clientId Unique client id of near server + * @param {Number} x Current org X position + * @param {Number} y Current org Y position + * @param {Number} dir Moving direction + * @param {String} orgJson Organism's serialized json + * @api + */ + _onMoveOrgFromServer(reqId, clientId, x, y, dir, orgJson) { + const reg = Connections.toRegion(clientId); + const conns = this.parent.conns; + this._moveToClient(Connections.toId(conns.oppositeRegion(reg, dir)), x, y, dir, orgJson, false); + } + /** * Moves organism from one client to another or to nearest server if * it's connected to current one @@ -59,15 +76,22 @@ class Api extends BaseApi { * @api */ _onMoveOrg(reqId, clientId, x, y, dir, orgJson) { - const reg = Connections.toRegion(clientId); - const side = this.parent.conns.side - 1; - + const reg = Connections.toRegion(clientId); + const side = this.parent.conns.side - 1; + // + // This organism came from client, served by current server. We have + // to move it to other client on current server + // if (dir === DIR.UP && reg[1] > 0 || dir === DIR.RIGHT && reg[0] < side || dir === DIR.DOWN && reg[1] < side || dir === DIR.LEFT && reg[0] > 0) { this._moveToClient(clientId, x, y, dir, orgJson); - } else { - this._moveToServer(clientId, x, y, dir, orgJson); + return; } + // + // This organism wants to move outside the current server - to the + // near server + // + this._moveToServer(clientId, x, y, dir, orgJson); } /** @@ -112,26 +136,20 @@ class Api extends BaseApi { * @param {Number} y Organism y coordinate * @param {Number} dir Moving direction * @param {String} orgJson Organism's serialized json + * @param {Boolean} fromClient false if organism came from near server */ - _moveToClient(clientId, x, y, dir, orgJson) { + _moveToClient(clientId, x, y, dir, orgJson, fromClient = true) { const region = Connections.toRegion(clientId); - if (dir === DIR.UP) {region[1]--} - else if (dir === DIR.RIGHT) {region[0]++} - else if (dir === DIR.DOWN) {region[1]++} - else if (dir === DIR.LEFT) {region[0]--} + if (fromClient) { + if (dir === DIR.UP) {region[1]--} + else if (dir === DIR.RIGHT) {region[0]++} + else if (dir === DIR.DOWN) {region[1]++} + else if (dir === DIR.LEFT) {region[0]--} + } const con = this.parent.conns.getConnection(region); - if (con.active) { - this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); - } else { - // TODO: possibly slow code - parse() do we really need this id? - const org = JSON.parse(orgJson); - const backRegion = Connections.toRegion(clientId); - const backCon = this.parent.conns.getConnection(backRegion); - this.parent.request(backCon.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); - Console.info(`Destination region ${region} is not active. Organism "${org.id}" will be sent back.`); - } + con.active && this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, clientId, x, y, dir, orgJson); } /** @@ -146,15 +164,7 @@ class Api extends BaseApi { const region = Connections.toRegion(clientId); const sock = this.parent.aroundServers.getSocket(dir); - if (sock) { - this.parent.request(sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); - } else { - // TODO: possibly slow code - parse() do we really need this id? - const org = JSON.parse(orgJson); - const backCon = this.parent.conns.getConnection(region); - this.parent.request(backCon.sock, TYPES.REQ_MOVE_ORG, x, y, dir, orgJson); - Console.error(`Destination server ${NAMES[dir]} is not active. Organism "${org.id}" will be sent back.`); - } + sock && this.parent.request(sock, TYPES.REQ_MOVE_ORG_FROM_SERVER, clientId, x, y, dir, orgJson); } /** diff --git a/server/src/share/Config.js b/server/src/share/Config.js index c765805..1624501 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -31,12 +31,12 @@ ServerConfig.init({ * with additional "around" rows and columns for connecting with sibling * servers. So, result amount of cells will be e.g.: 16 + 2 rows + 2 cols. */ - maxConnections: 100, + maxConnections: 1, /** * {Number} Port number for connecting with server. This value will be * passed to the server during creation */ - port: 8099, + port: 8200, /** * {Boolean} Means, that this server will be run in distributed mode. And * will be connected with near servers (up...left). false, means, that @@ -50,7 +50,7 @@ ServerConfig.init({ /** * {Number} Port number of server above. */ - upPort: 8100, + upPort: 8110, /** * {String} Host address of server on the right. Shouldn't contain port */ @@ -66,7 +66,7 @@ ServerConfig.init({ /** * {Number} Port number of server below */ - downPort: 8102, + downPort: 8100, /** * {String} Host address of server on the left. Shouldn't contain port */ From 2d639303a7c44963fa17d78d2510d61f6a0676cd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 16 Dec 2017 14:27:17 +0200 Subject: [PATCH 036/291] fixed few server to server protocol #13 --- client/src/manager/plugins/client/plugins/Api.js | 3 ++- client/src/share/Config.js | 4 ++-- common/src/Helper.js | 2 +- common/src/net/Api.js | 2 +- server/src/server/Server.js | 4 ++-- server/src/server/plugins/Api.js | 11 +++++++---- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 96203bd..14fef63 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -25,13 +25,14 @@ class Api extends BaseApi { /** * Is called if organism is move in from other Manager (world) * @param {String} reqId Unique request id + * @param {String} clientId Unique client id within current server * @param {Number} x Current org X position * @param {Number} y Current org Y position * @param {Number} dir Direction of moving * @param {String} orgJson Organism's serialized json * @api */ - _stepIn(reqId, x, y, dir, orgJson) { + _stepIn(reqId, clientId, x, y, dir, orgJson) { this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson); } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index cbe7140..02f5cd3 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -83,7 +83,7 @@ ClientConfig.init({ */ worldEnergyCheckPeriod: 10000, /** - * {Number} Mode for showing/supressing of messages. Possible values: + * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages * 1 - only important messages * 2 - no messages @@ -97,7 +97,7 @@ ClientConfig.init({ /** * {Number} Port number for connecting with server */ - serverPort: 8100, + serverPort: 8200, /** * {String} Host for connecting with server */ diff --git a/common/src/Helper.js b/common/src/Helper.js index 47f81b5..2a0686c 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -48,7 +48,7 @@ class Helper { } /** - * Sets first letter to lover case + * Sets first letter to lower case * @param {String} s * @returns {String} */ diff --git a/common/src/net/Api.js b/common/src/net/Api.js index 74fd4fe..c4aa861 100644 --- a/common/src/net/Api.js +++ b/common/src/net/Api.js @@ -33,7 +33,7 @@ class Api { this.parent = parent; /** * {WebSocket} Currently active socket. It's available only during - * message is received + * message is received in _onMessage() method */ this._sock = null; this._onMessageCb = this._onMessage.bind(this); diff --git a/server/src/server/Server.js b/server/src/server/Server.js index 2f3646c..d30a702 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -226,14 +226,14 @@ class Server extends Connection { const servers = this.aroundServers; const region = Connections.toRegion(clientId); const dir = servers ? servers.getDirection(sock) : clientId; - const isServer = dir !== clientId; + const isServer = dir < DIR.NO; !isServer && this.conns.clearData(region); sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); servers && servers.setSocket(sock, dir); - Console.warn(`Client '${isServer ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); + clientId !== false && Console.warn(`Client '${isServer ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); } } diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index c57613f..0e04c0c 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -20,7 +20,7 @@ class Api extends BaseApi { super(parent); const servers = parent.aroundServers; - this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrg.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrgFromClient.bind(this); this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this); this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); @@ -75,7 +75,7 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _onMoveOrg(reqId, clientId, x, y, dir, orgJson) { + _onMoveOrgFromClient(reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const side = this.parent.conns.side - 1; // @@ -234,12 +234,15 @@ class Api extends BaseApi { * state for nearest clients/Managers * @param {String} clientId Deactivated client id * @param {WebSocket} sock - * @private */ _onClose(clientId, sock) { const servers = this.parent.aroundServers; const dir = servers ? servers.getDirection(sock) : clientId; - + // + // This client was an extra client for current server. It means, that the + // server is full of other clients and there is no free slot for this + // + if (clientId === false) {return} if (dir === DIR.NO) { this._activateAround(Connections.toRegion(clientId), false); return; From e8ebebe5a86657755cca4f350c1cd9d64c36f6af Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 17 Dec 2017 02:03:42 +0200 Subject: [PATCH 037/291] VM speed optimizations --- client/src/manager/ManagerSpec.js | 4 +- client/src/manager/plugins/backup/Backup.js | 4 +- client/src/manager/plugins/ips/Ips.js | 2 +- .../src/manager/plugins/organisms/Config.js | 2 +- .../src/manager/plugins/organisms/Mutator.js | 28 +- .../src/manager/plugins/organisms/Organism.js | 18 +- .../manager/plugins/organisms/Organisms.js | 2 +- .../plugins/organisms/dos/Operators.js | 70 ++--- .../manager/plugins/organisms/dos/Organism.js | 2 +- .../plugins/organisms/dos/OrganismSpec.js | 6 +- .../plugins/organisms/garmin/Fitness.js | 2 +- .../plugins/organisms/garmin/Organism.js | 2 +- .../plugins/organisms/garmin/Organisms.js | 8 +- client/src/manager/plugins/status/Status.js | 2 +- client/src/vm/Num.js | 21 ++ client/src/vm/VM.js | 58 ++-- client/src/vm/VMSpec.js | 274 +++++++++--------- 17 files changed, 264 insertions(+), 241 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 0106889..abde352 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -344,7 +344,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.jsvm.code.push(0b00001101000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001101000000000000000000000000); // onStepDown() } else if (man2.organisms.size === 2) { destroy(); } @@ -411,7 +411,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { org1 = man1.organisms.first.val; - org1.jsvm.code.push(0b00001101000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001101000000000000000000000000); // onStepDown() man1.on(EVENTS.STEP_OUT, () => { expect(doneInc < 3).toBe(true); ++doneInc; diff --git a/client/src/manager/plugins/backup/Backup.js b/client/src/manager/plugins/backup/Backup.js index 97d7637..91f91ee 100644 --- a/client/src/manager/plugins/backup/Backup.js +++ b/client/src/manager/plugins/backup/Backup.js @@ -65,8 +65,8 @@ class Backup { mutationPeriod : org.mutationPeriod, mutationPercent : org.mutationPercent, color : org.color, - vars : org.jsvm.vars, - code : org.jsvm.cloneByteCode() + vars : org.vm.vars, + code : org.vm.cloneByteCode() }); cur = cur.next; } diff --git a/client/src/manager/plugins/ips/Ips.js b/client/src/manager/plugins/ips/Ips.js index ad2d94b..346626b 100644 --- a/client/src/manager/plugins/ips/Ips.js +++ b/client/src/manager/plugins/ips/Ips.js @@ -6,7 +6,7 @@ * {Boolean} show Shows/Hides IPS value at the top-left corner * {Number} periodMs Period of milliseconds, which is user for checking * IPS value. It's possible to increase it to reduce amount of - * requests and additional jsvm in main loop + * requests and additional vm in main loop * * @author flatline */ diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 844b028..dbf6ed2 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -149,7 +149,7 @@ const Config = { codeVarInitRange: 1000, /** * {Number} This value is amount of code lines, which will be run for one - * organism without interruption by one JSVM. Set this value to value bigger + * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ codeYieldPeriod: 10, diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 19fab12..543c7e2 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -22,18 +22,18 @@ const BITS_PER_VAR = Num.BITS_PER_VAR; class Mutator { static _onAdd(org) { - org.jsvm.insertLine(); + org.vm.insertLine(); org.changes += MAX_BITS; } static _onChange(org) { - const jsvm = org.jsvm; - jsvm.updateLine(Helper.rand(jsvm.size), Num.get()); + const vm = org.vm; + vm.updateLine(Helper.rand(vm.size), Num.get()); org.changes += MAX_BITS; } static _onDel(org) { - org.jsvm.removeLine(); + org.vm.removeLine(); org.changes += MAX_BITS; } @@ -44,19 +44,19 @@ class Mutator { */ static _onSmallChange(org) { const rand = Helper.rand; - const jsvm = org.jsvm; - const index = rand(jsvm.size); + const vm = org.vm; + const index = rand(vm.size); const rnd = rand(3); if (rnd === 0) { - jsvm.updateLine(index, Num.setOperator(jsvm.getLine(index), rand(jsvm.operators.operators.length))); + vm.updateLine(index, Num.setOperator(vm.getLine(index), rand(vm.operators.operators.length))); org.changes += MAX_BITS; } else if (rnd === 1) { - jsvm.updateLine(index, Num.setVar(jsvm.getLine(index), rand(VARS), rand(MAX_VAR))); + vm.updateLine(index, Num.setVar(vm.getLine(index), rand(VARS), rand(MAX_VAR))); org.changes += BITS_PER_VAR; } else { // toggle specified bit - jsvm.updateLine(index, jsvm.getLine(index) ^ (1 << rand(VAR_BITS_OFFS))); + vm.updateLine(index, vm.getLine(index) ^ (1 << rand(VAR_BITS_OFFS))); org.changes++; } } @@ -67,7 +67,7 @@ class Mutator { } static _onCopy(org) { - org.changes += (org.jsvm.copyLines() * MAX_BITS); + org.changes += (org.vm.copyLines() * MAX_BITS); } @@ -126,16 +126,16 @@ class Mutator { } _mutate(org, clone = true) { - const jsvm = org.jsvm; + const vm = org.vm; const probIndex = Helper.probIndex; const mTypes = this._MUTATION_TYPES; const maxSize = OConfig.codeMaxSize; - let mutations = Math.round(jsvm.size * (clone ? org.cloneMutationPercent : org.mutationPercent)) || 1; + let mutations = Math.round(vm.size * (clone ? org.cloneMutationPercent : org.mutationPercent)) || 1; let type; for (let i = 0; i < mutations; i++) { - if (jsvm.size > maxSize) {mutations = i; break} - type = jsvm.size < 1 ? 0 : probIndex(org.mutationProbs); + if (vm.size > maxSize) {mutations = i; break} + type = vm.size < 1 ? 0 : probIndex(org.mutationProbs); mTypes[type](org); } this._manager.fire(EVENTS.MUTATIONS, org, mutations, clone); diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 5e5217e..8e84b0d 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -11,7 +11,7 @@ const Config = require('./../../../share/Config').Config; const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENTS = require('./../../../share/Events').EVENTS; const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; -const JSVM = require('./../../../vm/VM'); +const VM = require('./../../../vm/VM'); const IS_NUM = Helper.isNumeric; @@ -117,7 +117,7 @@ class Organism extends Observer { // 'item' will be added after insertion iterations : this._iterations, fnId : this._fnId, - jsvm : this.jsvm.serialize(), + vm : this.vm.serialize(), energy : this._energy, color : this._color, mutationProbs : this._mutationProbs, @@ -147,7 +147,7 @@ class Organism extends Observer { // 'item' will be added after insertion this._iterations = json.iterations; this._fnId = json.fnId; - this.jsvm.unserialize(json.jsvm); + this.vm.unserialize(json.vm); this._energy = json.energy; this._color = json.color; this._mutationProbs = json.mutationProbs; @@ -166,7 +166,7 @@ class Organism extends Observer { } fitness() { - return Math.abs(OConfig.codeMaxSize - this.jsvm.size) * this._energy * this._changes; + return Math.abs(OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; } destroy() { @@ -175,8 +175,8 @@ class Organism extends Observer { this._energy = 0; this._item = null; this._mem = null; - this.jsvm && this.jsvm.destroy(); - this.jsvm = null; + this.vm && this.vm.destroy(); + this.vm = null; this._codeEndCb = null; super.destroy(); @@ -189,7 +189,7 @@ class Organism extends Observer { } _create() { - this.jsvm = new JSVM(this._codeEndCb.bind(this, this), this, this._operatorCls); + this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._color = OConfig.orgStartColor; this._mutationProbs = OConfig.orgMutationProbs.slice(); @@ -201,7 +201,7 @@ class Organism extends Observer { } _clone(parent) { - this.jsvm = new JSVM(this._codeEndCb.bind(this, this), this, this._operatorCls, parent.jsvm); + this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls, parent.vm); this._energy = parent.energy; this._color = parent.color; this._mutationProbs = parent.mutationProbs.slice(); @@ -234,7 +234,7 @@ class Organism extends Observer { */ _updateEnergy() { if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - const codeSize = this.jsvm.size; + const codeSize = this.vm.size; let grabSize = Math.floor(codeSize / OConfig.orgGarbagePeriod); if (grabSize < 1) {grabSize = 1} diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index d14b74b..b658041 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -265,7 +265,7 @@ class Organisms extends Configurable { let child = orgs.last.val; if (child.alive && looser.alive) { - child.changes += (child.jsvm.crossover(looser.jsvm) * MAX_BITS); + child.changes += (child.vm.crossover(looser.vm) * MAX_BITS); if (orgs.size >= OConfig.orgMaxOrgs) {looser.destroy()} } } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index da4e6ce..c3ba0b6 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -1,5 +1,5 @@ /** - * Digital Organisms Script - (DOS) is a simple language for JSVM. + * Digital Organisms Script - (DOS) is a simple language for VM. * This file contains all available operators implementation. For example: * for, if, variable declaration, steps, eating etc... User may override * this class for own needs and change operator list to custom. @@ -17,9 +17,9 @@ const Num = require('./../../../../vm/Num'); /** * {Function} Just a shortcuts */ -const VAR0 = Num.getVar; -const VAR1 = (n) => Num.getVar(n, 1); -const VAR2 = (n) => Num.getVar(n, 2); +const VAR0 = Num.getVar0; +const VAR1 = Num.getVar1; +const VAR2 = Num.getVar2; const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; const FOUR_BITS = 4; const BLOCK_MAX_LEN = OConfig.codeBitsPerBlock; @@ -27,6 +27,7 @@ const BITS_FOR_NUMBER = 16; const IS_NUM = Helper.isNumeric; const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; +const BITS = Num.getBits; class OperatorsDos extends Operators { constructor(offs, vars, obs) { @@ -95,27 +96,26 @@ class OperatorsDos extends Operators { * Parses variable operator. Format: var = number|var. 'num' bits format: * TODO: * - * @param {Num} num Packed into number vm line + * @param {Number} num Packed into number vm line * @param {Number} line Current line in vm * @return {Number} Parsed vm line string */ onVar(num, line) { - const vars = this.vars; - vars[VAR0(num)] = VAR2(num) < HALF_OF_VAR ? Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : vars[VAR1(num)]; - return line + 1; + this.vars[VAR0(num)] = VAR2(num) < HALF_OF_VAR ? BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : this.vars[VAR1(num)]; + return ++line; } //onFunc(num, line) { - // return line + 1; + // return ++line; //} onCondition(num, line, org, lines) { - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const val3 = BITS(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); const offs = this._getOffs(line, lines, val3); const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); if (this._CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { - return line + 1; + return ++line; } return offs; @@ -127,7 +127,7 @@ class OperatorsDos extends Operators { onLoop(num, line, org, lines, afterIteration = false) { const vars = this.vars; const var0 = VAR0(num); - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const val3 = BITS(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); const offs = this._getOffs(line, lines, val3); // // If last iteration has done and we've returned to the line, @@ -136,18 +136,18 @@ class OperatorsDos extends Operators { if (afterIteration === true) { if (++vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); - return line + 1; + return ++line; } return offs; } // // This is first time we are running "for" operator. No - // iterations hav done, yet + // iterations have done, yet // vars[var0] = vars[VAR1(num)]; if (vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); - return line + 1; + return ++line; } return offs; @@ -155,23 +155,23 @@ class OperatorsDos extends Operators { onOperator(num, line) { const vars = this.vars; - vars[VAR0(num)] = this._OPERATORS[Num.getBits(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); - return line + 1; + vars[VAR0(num)] = this._OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); + return ++line; } onNot(num, line) { this.vars[VAR0(num)] = +!this.vars[VAR1(num)]; - return line + 1; + return ++line; } //onPi(num, line) { // this.vars[VAR0(num)] = Math.PI; - // return line + 1; + // return ++line; //} //onTrig(num, line) { // this.vars[VAR0(num)] = this._TRIGS[VAR2(num)](this.vars[VAR1(num)]); - // return line + 1; + // return ++line; //} onLookAt(num, line, org) { @@ -181,27 +181,27 @@ class OperatorsDos extends Operators { if (!IS_NUM(x) || !IS_NUM(y) || Helper.normalize(x, y)[2] !== DIR.NO) { vars[VAR0(num)] = 0; - return line + 1; + return ++line; } let ret = {ret: 0}; this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); vars[VAR0(num)] = ret.ret; - return line + 1; + return ++line; } - onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); return line + 1} - onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); return line + 1} - onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); return line + 1} - onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); return line + 1} + onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); return ++line} + onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); return ++line} + onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} + onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} - onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y); return line + 1} - onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y); return line + 1} - onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1); return line + 1} - onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1); return line + 1} + onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y); return ++line} + onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y); return ++line} + onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1); return ++line} + onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1); return ++line} - onFromMem(num, line, org) {this.vars[VAR0(num)] = org.mem.pop() || 0; return line + 1} + onFromMem(num, line, org) {this.vars[VAR0(num)] = org.mem.pop() || 0; return ++line} onToMem(num, line, org) { const val = this.vars[VAR1(num)]; @@ -211,11 +211,11 @@ class OperatorsDos extends Operators { this.vars[VAR0(num)] = 0; } - return line + 1; + return ++line; } - onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; return line + 1} - onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; return line + 1} + onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; return ++line} + onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; return ++line} onCheckLeft(num, line, org) {return this._checkAt(num, line, org, org.x - 1, org.y)} onCheckRight(num, line, org) {return this._checkAt(num, line, org, org.x + 1, org.y)} @@ -226,7 +226,7 @@ class OperatorsDos extends Operators { const ret = {ret: 0}; org.fire(EVENTS.CHECK_AT, x, y, ret); this.vars[VAR0(num)] = ret.ret; - return line + 1; + return ++line; } _eat(org, num, x, y) { diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 536daa9..9215369 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -26,7 +26,7 @@ class OrganismDos extends Organism { } onRun() { - this.jsvm.run(this); + this.vm.run(this); } } diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index a971c73..6c82912 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -33,7 +33,7 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism creation from parent", () => { const parent = new OrganismDos(1, 3, 4, true, null, () => {}); - parent.jsvm.insertLine(); + parent.vm.insertLine(); parent.energy = 123; parent.changes = 0xaabbcc; parent._mutationProbs = [5,8,1,10,1,2,32,7]; @@ -45,8 +45,8 @@ describe("client/src/organism/OrganismDos", () => { let org = new OrganismDos(0, 1, 2, true, null, () => {}, parent); - expect(org.jsvm.code[0] === parent.jsvm.code[0]).toEqual(true); - expect(org.jsvm.size === parent.jsvm.size).toEqual(true); + expect(org.vm.code[0] === parent.vm.code[0]).toEqual(true); + expect(org.vm.size === parent.vm.size).toEqual(true); expect(org.energy === parent.energy).toEqual(true); expect(org.color === parent.color).toEqual(true); expect(THelper.compare(org.mutationProbs, parent.mutationProbs)).toEqual(true); diff --git a/client/src/manager/plugins/organisms/garmin/Fitness.js b/client/src/manager/plugins/organisms/garmin/Fitness.js index 91b882b..b2ae835 100644 --- a/client/src/manager/plugins/organisms/garmin/Fitness.js +++ b/client/src/manager/plugins/organisms/garmin/Fitness.js @@ -1962,7 +1962,7 @@ class FitnessGarmin { static _run(org, data, index) { const len = data.length; - const code = org.jsvm; + const code = org.vm; const vars = code.vars; for (let i = 0; i < len; i++) { diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index 5864185..37fdc35 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -29,7 +29,7 @@ class OrganismGarmin extends Organism { this._needRun = true; - this.jsvm.on(EVENTS.RESET_CODE, this._onResetCode.bind(this)); + this.vm.on(EVENTS.RESET_CODE, this._onResetCode.bind(this)); } onBeforeRun() { diff --git a/client/src/manager/plugins/organisms/garmin/Organisms.js b/client/src/manager/plugins/organisms/garmin/Organisms.js index 4f32498..cd09ad6 100644 --- a/client/src/manager/plugins/organisms/garmin/Organisms.js +++ b/client/src/manager/plugins/organisms/garmin/Organisms.js @@ -39,8 +39,8 @@ class Organisms extends BaseOrganisms { this._maxEnergy = org.energy; Console.warn('--------------------------------------------------'); Console.warn('Max energy: ', org.energy, ', org Id: ', org.id); - Console.warn('[' + org.jsvm.code + ']'); - Console.warn(this.manager.api.formatCode(org.jsvm.code)); + Console.warn('[' + org.vm.code + ']'); + Console.warn(this.manager.api.formatCode(org.vm.code)); } if (org.changes > this._maxChanges) {this._maxChanges = org.changes} @@ -77,8 +77,8 @@ class Organisms extends BaseOrganisms { this.manager.stop(); Console.warn('--------------------------------------------------'); Console.warn('org id: ', org.id, ', energy: ', org.energy); - Console.warn('[' + org.jsvm.code + ']'); - Console.warn(this.manager.api.formatCode(org.jsvm.code)); + Console.warn('[' + org.vm.code + ']'); + Console.warn(this.manager.api.formatCode(org.vm.code)); } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 81def18..3281e7f 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -81,7 +81,7 @@ class Status extends Configurable { while(item && (org = item.val)) { energy += org.energy; - codeSize += org.jsvm.size; + codeSize += org.vm.size; changes += org.changes; fitness += org.fitness(); item = item.next; diff --git a/client/src/vm/Num.js b/client/src/vm/Num.js index 9637b62..dbfce89 100644 --- a/client/src/vm/Num.js +++ b/client/src/vm/Num.js @@ -17,6 +17,11 @@ const MAX_OPERATOR = 1 << BITS_PER_OPERATOR; const VAR_BITS_OFFS = MAX_BITS - BITS_PER_OPERATOR; const BITS_WITHOUT_2_VARS = 1 << (VAR_BITS_OFFS - BITS_PER_VAR * 2); +const BITS_OF_VAR0 = BITS_PER_OPERATOR; +const BITS_OF_VAR1 = BITS_PER_OPERATOR + BITS_PER_VAR; +const BITS_OF_VAR2 = BITS_PER_OPERATOR + 2 * BITS_PER_VAR; +const BITS_OF_VAR3 = BITS_PER_OPERATOR + 3 * BITS_PER_VAR; + class Num { static get MAX_BITS() {return MAX_BITS} static get VAR_BITS_OFFS() {return VAR_BITS_OFFS} @@ -58,6 +63,22 @@ class Num { return num << (BITS_PER_OPERATOR + index * BITS_PER_VAR) >>> BITS_OF_FIRST_VAR; } + static getVar0(num) { + return num << BITS_OF_VAR0 >>> BITS_OF_FIRST_VAR; + } + + static getVar1(num) { + return num << BITS_OF_VAR1 >>> BITS_OF_FIRST_VAR; + } + + static getVar2(num) { + return num << BITS_OF_VAR2 >>> BITS_OF_FIRST_VAR; + } + + static getVar3(num) { + return num << BITS_OF_VAR3 >>> BITS_OF_FIRST_VAR; + } + /** * Sets variable bits into value 'val' and returns updated full number. * Example: _setVar(0xaabbccdd, 2, 0x3) -> 0x diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 10eed23..1e792ed 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -18,16 +18,20 @@ const Num = require('./Num'); * {Number} Maximum stack size, which may be used for recursion or function parameters */ const MAX_STACK_SIZE = 30000; +/** + * {Number} Index of first bit after operator bits + */ +const VAR_BITS_OFFS = Num.VAR_BITS_OFFS; -class JSVM extends Observer { +class VM extends Observer { /** - * Creates JSVM instance. codeEndCb will be called after last code line is run. - * parent is used if JSVM instance is in a cloning mode and we have to create + * Creates VM instance. codeEndCb will be called after last code line is run. + * parent is used if VM instance is in a cloning mode and we have to create * a copy of it. * @param {Function} codeEndCb * @param {Observer} obs Observer instance for Operators class * @param {Function} operatorCls Class of operators - * @param {JSVM} parent Parent JSVM instance in case of cloning + * @param {VM} parent Parent VM instance in case of cloning */ constructor(codeEndCb, obs, operatorCls, parent = null) { super(EVENT_AMOUNT); @@ -35,7 +39,7 @@ class JSVM extends Observer { this._obs = obs; /** * {Function} Class of operators, with implementation of all available - * script parts for current JSVM instance + * script parts for current VM instance */ this._operatorCls = operatorCls; /** @@ -54,6 +58,7 @@ class JSVM extends Observer { * {Function} Class, which implement all supported operators */ this._operators = new operatorCls(this._offsets, this._vars, obs); + this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; this._line = 0; this._linesRun = 0; @@ -77,10 +82,10 @@ class JSVM extends Observer { } unserialize(json) { - this._offsets = json.offsets; - this._vars = json.vars; - this._code = json.code; - this._line = json.line; + this._offsets = json.offsets; + this._vars = json.vars; + this._code = json.code; + this._line = json.line; this._operators = new this._operatorCls(this._offsets, this._vars, this._obs); } @@ -91,18 +96,17 @@ class JSVM extends Observer { * @param {Organism} org Current organism */ run(org) { - let line = this._line; - let code = this._code; - let lines = code.length; - let len = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; - let len2 = len; - let ops = this._operators.operators; - let getOp = Num.getOperator; - let ret = false; - let offs = this._offsets; + const code = this._code; + const lines = code.length; + const ops = this._ops; + const offs = this._offsets; + let line = this._line; + let len = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; + let len2 = len; + let ret = false; while (len-- > 0 && org.alive) { - line = ops[getOp(code[line])](code[line], line, org, lines, ret); + line = ops[code[line] >>> VAR_BITS_OFFS](code[line], line, org, lines, ret); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) @@ -115,10 +119,8 @@ class JSVM extends Observer { if (line >= lines) { line = 0; org.alive && (this._operators.offsets = (this._offsets = [])); - if (this._onCodeEnd) { - this._onCodeEnd(this._linesRun + (len2 - len)); - this._linesRun = -(len2 - len); - } + this._onCodeEnd(this._linesRun + (len2 - len)); + this._linesRun = -(len2 - len); break; } } @@ -149,13 +151,13 @@ class JSVM extends Observer { * end1 : 2 * jsvm1.crossover(jsvm2) // [4,5,6] instead [2,3] ->, jsvm1 === [1,4,5,6] * - * @param {JSVM} jsvm JSVM instance, from where we have to cut code part + * @param {VM} vm VM instance, from where we have to cut code part * @returns {Number} Amount of changes in current (this) vm */ - crossover(jsvm) { + crossover(vm) { const rand = Helper.rand; const len = this._code.length; - const len1 = jsvm.code.length; + const len1 = vm.code.length; let start = rand(len); let end = rand(len); let start1 = rand(len1); @@ -173,7 +175,7 @@ class JSVM extends Observer { if (this._code.length + adds >= OConfig.codeMaxSize) { return 0 } - this._code.splice.apply(this._code, [start, end - start + 1].concat(jsvm.code.slice(start1, end1 + 1))); + this._code.splice.apply(this._code, [start, end - start + 1].concat(vm.code.slice(start1, end1 + 1))); this._reset(); return adds; @@ -268,4 +270,4 @@ class JSVM extends Observer { } } -module.exports = JSVM; \ No newline at end of file +module.exports = VM; \ No newline at end of file diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 7037510..1ccff90 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,11 +1,11 @@ -describe("client/src/organism/JSVM", () => { +describe("client/src/organism/VM", () => { let Observer = require('./../../../common/src/Observer'); let Helper = require('./../../../common/src/Helper'); let THelper = require('./../../../common/tests/Helper'); let Config = require('./../share/Config').Config; let OConfig = require('./../manager/plugins/organisms/Config'); let api = require('./../share/Config').api; - let JSVM = require('./VM'); + let VM = require('./VM'); let Num = require('./Num'); let Operators = require('./Operators'); let cls = null; @@ -13,85 +13,85 @@ describe("client/src/organism/JSVM", () => { it("Checking vm creation", () => { let flag = false; const obs = new Observer(1); - const jsvm = new JSVM(() => flag = true, obs, () => {}); + const vm = new VM(() => flag = true, obs, () => {}); - jsvm.run(); + vm.run(); expect(flag).toEqual(false); - jsvm.destroy(); + vm.destroy(); }); it("Checking parent argument and 'cloning' mode", () => { const obs = new Observer(1); - const parent = new JSVM(() => {}, obs, () => {}); + const parent = new VM(() => {}, obs, () => {}); parent.insertLine(); - const jsvm = new JSVM(() => {}, obs, () => {}, parent); + const vm = new VM(() => {}, obs, () => {}, parent); - expect(jsvm.code[0] === parent.code[0]).toEqual(true); - expect(jsvm.size === parent.size).toEqual(true); - expect(jsvm.vars[0] === parent.vars[0]).toEqual(true); + expect(vm.code[0] === parent.code[0]).toEqual(true); + expect(vm.size === parent.size).toEqual(true); + expect(vm.vars[0] === parent.vars[0]).toEqual(true); parent.destroy(); - jsvm.destroy(); + vm.destroy(); }); it("Checking 'vars' getter for non 'cloning' mode", () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - expect(jsvm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); + expect(vm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); - jsvm.destroy(); + vm.destroy(); }); it("Checking no code size", () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - expect(jsvm.size).toEqual(0); - jsvm.run(); - expect(jsvm.size).toEqual(0); + expect(vm.size).toEqual(0); + vm.run(); + expect(vm.size).toEqual(0); - jsvm.destroy(); + vm.destroy(); }); it("Checking destroy", () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - jsvm.destroy(); - expect(jsvm.code).toEqual(null); + vm.destroy(); + expect(vm.code).toEqual(null); }); it("Checking 'code' and 'size' properties", () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - expect(jsvm.code instanceof Array).toEqual(true); - expect(jsvm.size).toEqual(0); + expect(vm.code instanceof Array).toEqual(true); + expect(vm.size).toEqual(0); - jsvm.insertLine(); - expect(jsvm.code instanceof Array).toEqual(true); - expect(jsvm.size).toEqual(1); + vm.insertLine(); + expect(vm.code instanceof Array).toEqual(true); + expect(vm.size).toEqual(1); - jsvm.insertLine(); - expect(jsvm.size).toEqual(2); - jsvm.removeLine(); - expect(jsvm.size).toEqual(1); - jsvm.removeLine(); - expect(jsvm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(2); + vm.removeLine(); + expect(vm.size).toEqual(1); + vm.removeLine(); + expect(vm.size).toEqual(0); - jsvm.destroy(); + vm.destroy(); }); it("Checking 'operators' property", () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, Operators); + const vm = new VM(() => {}, obs, Operators); - expect(jsvm.operators instanceof Operators).toEqual(true); + expect(vm.operators instanceof Operators).toEqual(true); - jsvm.destroy(); + vm.destroy(); }); // it("Checking run method", () => { @@ -101,7 +101,7 @@ describe("client/src/organism/JSVM", () => { // get size () {return 1} // } // const obs = new Observer(1); - // const vm = new JSVM(() => {}, obs, () => {}); + // const vm = new VM(() => {}, obs, () => {}); // const coc = api.get('codeOperatorsCls'); // const yp = api.get('codeYieldPeriod'); // const fc = api.get('codeFitnessCls'); @@ -123,8 +123,8 @@ describe("client/src/organism/JSVM", () => { it("Checking crossover with increasing child code", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -164,8 +164,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with decreasing child code", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -203,8 +203,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with the same child code size", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -243,8 +243,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size in parents", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); jsvm1.crossover(jsvm2); expect(jsvm1.size).toEqual(0); @@ -255,8 +255,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size for one parent and twp lines of code for other", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -285,8 +285,8 @@ describe("client/src/organism/JSVM", () => { }); it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { const obs = new Observer(1); - const jsvm1 = new JSVM(() => {}, obs, () => {}); - const jsvm2 = new JSVM(() => {}, obs, () => {}); + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); const rand = Helper.rand; let i = -1; @@ -317,42 +317,42 @@ describe("client/src/organism/JSVM", () => { it('Checking insertLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - expect(jsvm.size).toEqual(0); - jsvm.insertLine(); - expect(jsvm.size).toEqual(1); - jsvm.insertLine(); - expect(jsvm.size).toEqual(2); + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + vm.insertLine(); + expect(vm.size).toEqual(2); - jsvm.destroy(); + vm.destroy(); }); it('Checking insertLine() method 2', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; - expect(jsvm.size).toEqual(0); - jsvm.insertLine(); - expect(jsvm.size).toEqual(1); + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); - expect(jsvm.code[0]).toEqual(0xabcdefff); + expect(vm.code[0]).toEqual(0xabcdefff); Num.get = get; - jsvm.destroy(); + vm.destroy(); }); it('Checking copyLines() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); Helper.rand = function (n) { i++; if (i === 0) { // start @@ -365,25 +365,25 @@ describe("client/src/organism/JSVM", () => { return 0; } }; - expect(jsvm.size).toEqual(4); - jsvm.copyLines(); - expect(jsvm.size).toEqual(6); - expect(jsvm.code[0]).toEqual(jsvm.code[3]); - expect(jsvm.code[1]).toEqual(jsvm.code[4]); + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[0]).toEqual(vm.code[3]); + expect(vm.code[1]).toEqual(vm.code[4]); Helper.rand = rand; - jsvm.destroy(); + vm.destroy(); }); it('Checking copyLines() method 2', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); Helper.rand = function (n) { i++; if (i === 0) { // start @@ -396,25 +396,25 @@ describe("client/src/organism/JSVM", () => { return 0; } }; - expect(jsvm.size).toEqual(4); - jsvm.copyLines(); - expect(jsvm.size).toEqual(6); - expect(jsvm.code[1]).toEqual(jsvm.code[3]); - expect(jsvm.code[2]).toEqual(jsvm.code[4]); + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[1]).toEqual(vm.code[3]); + expect(vm.code[2]).toEqual(vm.code[4]); Helper.rand = rand; - jsvm.destroy(); + vm.destroy(); }); it('Checking copyLines() method 3', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); - jsvm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); Helper.rand = function (n) { i++; if (i === 0) { // start @@ -427,92 +427,92 @@ describe("client/src/organism/JSVM", () => { return 1; } }; - expect(jsvm.size).toEqual(4); - jsvm.copyLines(); - expect(jsvm.size).toEqual(6); - expect(jsvm.code[1]).toEqual(jsvm.code[4]); - expect(jsvm.code[2]).toEqual(jsvm.code[5]); + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[1]).toEqual(vm.code[4]); + expect(vm.code[2]).toEqual(vm.code[5]); Helper.rand = rand; - jsvm.destroy(); + vm.destroy(); }); it('Checking copyLines() method with no code', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; Helper.rand = () => 0; - expect(jsvm.size).toEqual(0); - jsvm.copyLines(); - expect(jsvm.size).toEqual(0); + expect(vm.size).toEqual(0); + vm.copyLines(); + expect(vm.size).toEqual(0); Helper.rand = rand; - jsvm.destroy(); + vm.destroy(); }); it('Checking updateLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; - jsvm.insertLine(); - expect(jsvm.code[0]).toEqual(0xabcdefff); + vm.insertLine(); + expect(vm.code[0]).toEqual(0xabcdefff); - jsvm.updateLine(0, 0xffffffff); - expect(jsvm.code[0]).toEqual(0xffffffff); + vm.updateLine(0, 0xffffffff); + expect(vm.code[0]).toEqual(0xffffffff); - jsvm.updateLine(0, 0x12345678); - expect(jsvm.code[0]).toEqual(0x12345678); + vm.updateLine(0, 0x12345678); + expect(vm.code[0]).toEqual(0x12345678); Num.get = get; - jsvm.destroy(); + vm.destroy(); }); it('Checking removeLine() method', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - jsvm.insertLine(); - expect(jsvm.size).toEqual(1); - jsvm.removeLine(); - expect(jsvm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + vm.removeLine(); + expect(vm.size).toEqual(0); - jsvm.destroy(); + vm.destroy(); }); it('Checking removeLine() for empty code', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); - expect(jsvm.size).toEqual(0); - jsvm.removeLine(); - expect(jsvm.size).toEqual(0); - jsvm.removeLine(); - expect(jsvm.size).toEqual(0); + expect(vm.size).toEqual(0); + vm.removeLine(); + expect(vm.size).toEqual(0); + vm.removeLine(); + expect(vm.size).toEqual(0); - jsvm.destroy(); + vm.destroy(); }); it('Checking getLine()', () => { const obs = new Observer(2); - const jsvm = new JSVM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let get = Num.get; Num.get = () => 0xabcdefff; - expect(jsvm.size).toEqual(0); - expect(jsvm.getLine(0)).toEqual(undefined); - expect(jsvm.getLine(1)).toEqual(undefined); - jsvm.insertLine(); - expect(jsvm.size).toEqual(1); - expect(jsvm.getLine(0)).toEqual(0xabcdefff); - - jsvm.removeLine(); - expect(jsvm.size).toEqual(0); - expect(jsvm.getLine(0)).toEqual(undefined); - expect(jsvm.getLine(1)).toEqual(undefined); - expect(jsvm.getLine(9)).toEqual(undefined); + expect(vm.size).toEqual(0); + expect(vm.getLine(0)).toEqual(undefined); + expect(vm.getLine(1)).toEqual(undefined); + vm.insertLine(); + expect(vm.size).toEqual(1); + expect(vm.getLine(0)).toEqual(0xabcdefff); + + vm.removeLine(); + expect(vm.size).toEqual(0); + expect(vm.getLine(0)).toEqual(undefined); + expect(vm.getLine(1)).toEqual(undefined); + expect(vm.getLine(9)).toEqual(undefined); Num.get = get; - jsvm.destroy(); + vm.destroy(); }); }); \ No newline at end of file From 3206464ae1c41a7008e4b49729d736fbd13f8d7a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 18 Dec 2017 00:11:48 +0200 Subject: [PATCH 038/291] fixed server's console messages VM code style refactoring fixed an issue of two server son the same port #13 --- client/src/App.js | 8 +++++++- client/src/vm/VM.js | 20 ++++++++++---------- server/src/server/Client.js | 2 +- server/src/server/Connections.js | 4 +++- server/src/server/Server.js | 3 ++- server/src/share/Config.js | 2 +- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index 85f6589..6f12420 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -23,5 +23,11 @@ * * @author flatline */ +//const VM = require('./vm/VM'); +//const Operators = require('./manager/plugins/organisms/dos/Operators'); + const Manager = require('./manager/Manager'); -(window.man = new Manager()).run(); \ No newline at end of file +(window.man = new Manager()).run(); +//setTimeout(() => window.man.stop(), 2000); +//window.VM = VM; +//window.Operators = Operators; \ No newline at end of file diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 1e792ed..2a4c352 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -100,9 +100,9 @@ class VM extends Observer { const lines = code.length; const ops = this._ops; const offs = this._offsets; + const len2 = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; + let len = len2; let line = this._line; - let len = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; - let len2 = len; let ret = false; while (len-- > 0 && org.alive) { @@ -155,14 +155,14 @@ class VM extends Observer { * @returns {Number} Amount of changes in current (this) vm */ crossover(vm) { - const rand = Helper.rand; - const len = this._code.length; - const len1 = vm.code.length; - let start = rand(len); - let end = rand(len); - let start1 = rand(len1); - let end1 = rand(len1); - let adds; + const rand = Helper.rand; + const len = this._code.length; + const len1 = vm.code.length; + const start = rand(len); + const end = rand(len); + const start1 = rand(len1); + const end1 = rand(len1); + let adds; if (start > end) { [start, end] = [end, start] diff --git a/server/src/server/Client.js b/server/src/server/Client.js index 0e326bc..a90705b 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -43,7 +43,7 @@ class Client extends BaseClient { */ onError(event) { super.onError(event); - Console.error(`'${NAMES[this._dir]}' server error: ${event.message} on ${this.host}:${this.port}`); + Console.warn(`'${NAMES[this._dir]}' server error: ${event.message} on ${this.host}:${this.port}`); } /** diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index c0ad245..243230d 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -36,7 +36,9 @@ class Connections { } constructor(amount) { + const side = +Math.sqrt(amount).toFixed(); if (amount < 1) {throw `Incorrect amount of connections in class Connections - ${amount}`} + if (side * side !== amount) {throw `Incorrect amount of connections in class Connections - ${amount}. Should be a pow of two`} /** * {Number} Size of one side of MAX_CONNECTIONS qub. Contains additional * "around" rows and columns. For qub == 16, it's 4. @@ -45,7 +47,7 @@ class Connections { /** * {Number} Size of one full side of the connections squire */ - this._side = +Math.sqrt(amount).toFixed(); + this._side = side; for (let col = 0, conns = this.conns; col < this._side; col++) { conns[col] = (new Array(this._side)).fill(null); diff --git a/server/src/server/Server.js b/server/src/server/Server.js index d30a702..dfee317 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -116,8 +116,9 @@ class Server extends Connection { }; this.aroundServers && this.aroundServers.run(onDone) || onDone(); }); + this._server.on('error', (e) => Console.error(`Can\'t run server on port ${this._port}. Error: '${e.message}'`)); } catch (e) { - Console.warn(`Can\'t run server on port ${this._port}. Error: ${e.message}`); + Console.error(`Can\'t run server on port ${this._port}. Error: '${e.message}'`); return false; } diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 1624501..83e564d 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -36,7 +36,7 @@ ServerConfig.init({ * {Number} Port number for connecting with server. This value will be * passed to the server during creation */ - port: 8200, + port: 8201, /** * {Boolean} Means, that this server will be run in distributed mode. And * will be connected with near servers (up...left). false, means, that From 14836bbba7a33336c9ca5171d57e10fdf97d60a4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 18 Dec 2017 00:47:39 +0200 Subject: [PATCH 039/291] fixed few tests #83 --- client/src/vm/VM.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 2a4c352..e2811f1 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -158,10 +158,10 @@ class VM extends Observer { const rand = Helper.rand; const len = this._code.length; const len1 = vm.code.length; - const start = rand(len); - const end = rand(len); - const start1 = rand(len1); - const end1 = rand(len1); + let start = rand(len); + let end = rand(len); + let start1 = rand(len1); + let end1 = rand(len1); let adds; if (start > end) { From b18c944b9394f5b231f5475731ac83ad6cd45fa1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 18 Dec 2017 16:38:49 +0200 Subject: [PATCH 040/291] fixed few tests #13 --- client/src/manager/ManagerSpec.js | 6 ++++ .../src/manager/plugins/client/plugins/Api.js | 4 +-- common/src/plugins/Plugins.js | 30 +++++++++---------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 0106889..d89dfdb 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -16,6 +16,8 @@ describe("client/src/manager/Manager", () => { const waitEvent = THelper.waitEvent; const wait = THelper.wait; const host = Config.serverHost; + const port = SConfig.port; + const maxConns = SConfig.maxConnections; let error; let warn; @@ -39,6 +41,8 @@ describe("client/src/manager/Manager", () => { Config.modeNodeJs = true; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; + SConfig.maxConnections = 100; error = Console.error; warn = Console.warn; @@ -67,6 +71,8 @@ describe("client/src/manager/Manager", () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; Config.serverHost = host; SConfig.modeDistributed = dist; + SConfig.port = port; + SConfig.maxConnections = maxConns; }); it("Checking manager creation", (done) => { diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 96203bd..4d85ffd 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -7,7 +7,6 @@ const TYPES = require('./../../../../../../common/src/net/Requests').TYPES; const BaseApi = require('./../../../../../../common/src/net/Api'); const EVENTS = require('./../../../../share/Events').EVENTS; -const Console = require('./../../../../share/Console'); class Api extends BaseApi { constructor(client) { @@ -25,13 +24,14 @@ class Api extends BaseApi { /** * Is called if organism is move in from other Manager (world) * @param {String} reqId Unique request id + * @param {String} clientId Unique client id on current server * @param {Number} x Current org X position * @param {Number} y Current org Y position * @param {Number} dir Direction of moving * @param {String} orgJson Organism's serialized json * @api */ - _stepIn(reqId, x, y, dir, orgJson) { + _stepIn(reqId, clientId, x, y, dir, orgJson) { this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson); } diff --git a/common/src/plugins/Plugins.js b/common/src/plugins/Plugins.js index 1b6bc16..7a1f5c1 100644 --- a/common/src/plugins/Plugins.js +++ b/common/src/plugins/Plugins.js @@ -44,21 +44,6 @@ class Plugins { return require(path); } - _onRun(done = () => {}) {this._async.run(done)} - _onStop(done = () => {}) {this._async.stop(done)} - - _createPlugins(parent, cfg) { - const parentPlugins = parent.plugins = []; - - for (let p of cfg.plugins) { - const path = p.path || p; - const name = path.split('/').slice(-1)[0]; - let pluginCls = this.require(path); - - parentPlugins.push(new (pluginCls[name] || pluginCls)(parent, p.cfg || {})); - } - } - /** * Is called if parent instance calls destroy() method. Here we * destroy all created plugins and the reference to this instance @@ -94,6 +79,21 @@ class Plugins { // me._async ? me._async.stop(onAfterDestroy) : onAfterDestroy(); } + + _onRun(done = () => {}) {this._async.run(done)} + _onStop(done = () => {}) {this._async.stop(done)} + + _createPlugins(parent, cfg) { + const parentPlugins = parent.plugins = []; + + for (let p of cfg.plugins) { + const path = p.path || p; + const name = path.split('/').slice(-1)[0]; + let pluginCls = this.require(path); + + parentPlugins.push(new (pluginCls[name] || pluginCls)(parent, p.cfg || {})); + } + } } module.exports = Plugins; \ No newline at end of file From afd1f95b961a8eb38eadc6e2288f98ca2541e86f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 19 Dec 2017 18:42:00 +0200 Subject: [PATCH 041/291] fixed one test #13 --- client/src/manager/ManagerSpec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index abde352..7ba498e 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -16,6 +16,7 @@ describe("client/src/manager/Manager", () => { const waitEvent = THelper.waitEvent; const wait = THelper.wait; const host = Config.serverHost; + const port = SConfig.port; let error; let warn; @@ -39,6 +40,7 @@ describe("client/src/manager/Manager", () => { Config.modeNodeJs = true; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; error = Console.error; warn = Console.warn; @@ -67,6 +69,7 @@ describe("client/src/manager/Manager", () => { jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; Config.serverHost = host; SConfig.modeDistributed = dist; + SConfig.port = port; }); it("Checking manager creation", (done) => { From 4115735a7395311fc29fadabe86aea8bbad35a91 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 20 Dec 2017 00:15:13 +0200 Subject: [PATCH 042/291] fixed an issue with zero clone mutations VM optimizations --- .../src/manager/plugins/organisms/Config.js | 14 +++---- .../src/manager/plugins/organisms/Organism.js | 3 +- .../manager/plugins/organisms/Organisms.js | 17 +++++---- .../plugins/organisms/dos/Operators.js | 38 +++++++++---------- .../plugins/organisms/dos/Organisms.js | 2 +- 5 files changed, 35 insertions(+), 39 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index dbf6ed2..0059f4f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -40,7 +40,7 @@ const Config = { * clonePeriod - Probability of change clone energy percent value * ] */ - orgMutationProbs: [50,80,10,100,1,10,10,10,10,10], + orgMutationProbs: [10,1,1,100,1,1,1,1,1,1], /** * {Number} Max value, which we may use in orgMutationProbs array. We may use * range: [0...orgMutationProbsMaxValue] including these values @@ -50,7 +50,7 @@ const Config = { * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ - orgCloneMutationPercent: 0.01, + orgCloneMutationPercent: 0.000, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ @@ -59,13 +59,13 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 1000, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 10000, + orgRainMutationPeriod: 500, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -80,7 +80,7 @@ const Config = { * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 10000, + orgStartEnergy: 100000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB @@ -112,7 +112,7 @@ const Config = { /** * {Number} Size of organism stack (internal memory) */ - orgMemSize: 64, + orgMemSize: 1024, /** * {Number} Percent of energy, which will be given to the child */ @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 300, + codeIterationsPerOnce: 1000, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 8e84b0d..9e22b64 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -7,7 +7,6 @@ */ const Observer = require('./../../../../../common/src/Observer'); const Helper = require('./../../../../../common/src/Helper'); -const Config = require('./../../../share/Config').Config; const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENTS = require('./../../../share/Events').EVENTS; const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; @@ -117,7 +116,7 @@ class Organism extends Observer { // 'item' will be added after insertion iterations : this._iterations, fnId : this._fnId, - vm : this.vm.serialize(), + vm : this.vm.serialize(), energy : this._energy, color : this._color, mutationProbs : this._mutationProbs, diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index b658041..ee36980 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -12,7 +12,7 @@ const Config = require('./../../../../src/share/Config').Config; const OConfig = require('./Config'); const Console = require('./../../../../src/share/Console'); const EVENTS = require('./../../../../src/share/Events').EVENTS; -const Backup = require('./../backup/Backup'); +//const Backup = require('./../backup/Backup'); const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); @@ -30,13 +30,6 @@ class Organisms extends Configurable { */ compare(org1, org2) {} - /** - * Is called every time after organism's code was run - * @param {Organism} org - * @abstract - */ - onOrganism(org) {} - /** * Is called after moving of organism is done. Updates Manager.positions * map with a new position of organism @@ -136,6 +129,14 @@ class Organisms extends Configurable { this.updateCreate(); } + /** + * Is called every time after organism's code was run + * @param {Organism} org + */ + onOrganism(org) { + org.alive && org.vm.size === 0 && this._onCodeEnd(org, 0); + } + addOrgHandlers(org) { org.on(EVENTS.DESTROY, this._onKillOrg.bind(this)); } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index c3ba0b6..0d829dd 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -9,7 +9,6 @@ const DIR = require('./../../../../../../common/src/Directions').DIR; const Helper = require('./../../../../../../common/src/Helper'); const EVENTS = require('./../../../../../src/share/Events').EVENTS; -const Config = require('./../../../../../src/share/Config').Config; const OConfig = require('./../Config'); const Operators = require('./../../../../vm/Operators'); const Num = require('./../../../../vm/Num'); @@ -29,6 +28,16 @@ const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; const BITS = Num.getBits; +/** + * {Array} Available conditions for if operator. Amount should be + * the same like (1 << BITS_PER_VAR) + */ +const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; +/** + * {Array} Available operators for math calculations + */ +const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; + class OperatorsDos extends Operators { constructor(offs, vars, obs) { super(offs, vars, obs); @@ -42,7 +51,7 @@ class OperatorsDos extends Operators { this.onCondition.bind(this), this.onLoop.bind(this), this.onOperator.bind(this), - this.onNot.bind(this), + //this.onNot.bind(this), //this.onPi.bind(this), //this.onTrig.bind(this), this.onLookAt.bind(this), @@ -63,17 +72,6 @@ class OperatorsDos extends Operators { this.onCheckUp.bind(this), this.onCheckDown.bind(this) ]; - /** - * {Array} Available conditions for if operator. Amount should be - * the same like (1 << BITS_PER_VAR) - */ - this._CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; - /** - * {Array} Available operators for math calculations - */ - this._OPERATORS = [ - (a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b) - ]; //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // // We have to set amount of available operators for correct @@ -85,8 +83,6 @@ class OperatorsDos extends Operators { destroy() { super.destroy(); this._OPERATORS_CB = null; - this._CONDITIONS = null; - this._OPERATORS = null; //this._TRIGS = null; } @@ -114,7 +110,7 @@ class OperatorsDos extends Operators { const offs = this._getOffs(line, lines, val3); const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); - if (this._CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { + if (CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { return ++line; } @@ -155,14 +151,14 @@ class OperatorsDos extends Operators { onOperator(num, line) { const vars = this.vars; - vars[VAR0(num)] = this._OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); + vars[VAR0(num)] = OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); return ++line; } - onNot(num, line) { - this.vars[VAR0(num)] = +!this.vars[VAR1(num)]; - return ++line; - } + // onNot(num, line) { + // this.vars[VAR0(num)] = +!this.vars[VAR1(num)]; + // return ++line; + // } //onPi(num, line) { // this.vars[VAR0(num)] = Math.PI; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index dff7351..8127c56 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -53,7 +53,7 @@ class Organisms extends BaseOrganisms { * @override */ onBeforeClone(org) { - return org.energy > 0; + return org.energy > 1; } /** From 4517e5565615787d38ecfe65c546c0d533696550 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 20 Dec 2017 09:57:29 +0200 Subject: [PATCH 043/291] fixed tests #13 --- client/src/manager/ManagerSpec.js | 3 +++ client/src/manager/plugins/client/ClientSpec.js | 8 ++++++-- client/src/vm/VM.js | 10 ++++++---- server/src/server/ServerSpec.js | 6 +++--- server/src/server/plugins/ApiSpec.js | 4 +++- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 8fdbfb0..fb89ed3 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -18,6 +18,7 @@ describe("client/src/manager/Manager", () => { const host = Config.serverHost; const port = SConfig.port; const maxConns = SConfig.maxConnections; + const startOrgs = OConfig.orgStartAmount; let error; let warn; @@ -43,6 +44,7 @@ describe("client/src/manager/Manager", () => { SConfig.modeDistributed = false; SConfig.port = Config.serverPort; SConfig.maxConnections = 100; + OConfig.orgStartAmount = 0; error = Console.error; warn = Console.warn; @@ -73,6 +75,7 @@ describe("client/src/manager/Manager", () => { SConfig.modeDistributed = dist; SConfig.port = port; SConfig.maxConnections = maxConns; + OConfig.orgStartAmount = startOrgs; }); it("Checking manager creation", (done) => { diff --git a/client/src/manager/plugins/client/ClientSpec.js b/client/src/manager/plugins/client/ClientSpec.js index 7f792d3..d0d121a 100644 --- a/client/src/manager/plugins/client/ClientSpec.js +++ b/client/src/manager/plugins/client/ClientSpec.js @@ -9,11 +9,11 @@ describe("client/src/manager/plugins/Client", () => { let api = require('./../../../share/Config').api; let Console = require('./../../../share/Console'); let SConsole = require('./../../../../../server/src/share/Console'); - const Api = require('./../../../../../server/src/server/plugins/Api'); - const Request = require('./../../../../../common/src/plugins/Request'); const waitEvent = THelper.waitEvent; const wait = THelper.wait; const host = Config.serverHost; + const port = SConfig.port; + const maxConns = SConfig.maxConnections; let isNodeJs; let Client; let CEVENTS; @@ -36,6 +36,8 @@ describe("client/src/manager/plugins/Client", () => { Config.serverHost = 'ws://127.0.0.1'; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; + SConfig.maxConnections = 100; Client = require('./Client').Client; CEVENTS = require('./Client').EVENTS; Server = require('./../../../../../server/src/server/Server').Server; @@ -68,6 +70,8 @@ describe("client/src/manager/plugins/Client", () => { Config.serverHost = host; SConfig.modeDistributed = dist; + SConfig.port = port; + SConfig.maxConnections = maxConns; }); it("Checking client creation without server", (done) => { diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index e2811f1..82ac711 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -117,10 +117,12 @@ class VM extends Observer { continue; } if (line >= lines) { - line = 0; - org.alive && (this._operators.offsets = (this._offsets = [])); - this._onCodeEnd(this._linesRun + (len2 - len)); - this._linesRun = -(len2 - len); + if (org.alive) { + line = 0; + this._operators.offsets = this._offsets = []; + this._onCodeEnd(this._linesRun + (len2 - len)); + this._linesRun = -(len2 - len); + } break; } } diff --git a/server/src/server/ServerSpec.js b/server/src/server/ServerSpec.js index 1fa5959..e7b73c6 100644 --- a/server/src/server/ServerSpec.js +++ b/server/src/server/ServerSpec.js @@ -13,11 +13,9 @@ describe("server/src/server/Server", () => { const SConsole = require('./../share/Console'); const Console = require('./../../../client/src/share/Console'); const Helper = require('./../../../common/tests/Helper'); - const TYPES = require('./../../../common/src/net/Requests').TYPES; - const Api = require('./plugins/Api'); - const Request = require('./../../../common/src/plugins/Request'); const waitEvent = Helper.waitEvent; const host = Config.serverHost; + const port = SConfig.port; const CLIENT_URL = `ws://127.0.0.1:${Config.serverPort}`; @@ -33,6 +31,7 @@ describe("server/src/server/Server", () => { Config.serverHost = 'ws://127.0.0.1'; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; error = Console.error; warn = Console.warn; info = Console.info; @@ -58,6 +57,7 @@ describe("server/src/server/Server", () => { Config.modeNodeJs = OLD_MODE; Config.serverHost = host; SConfig.modeDistributed = dist; + SConfig.port = port; }); it("Checking server creation", () => { diff --git a/server/src/server/plugins/ApiSpec.js b/server/src/server/plugins/ApiSpec.js index 3b4a35b..93b848b 100644 --- a/server/src/server/plugins/ApiSpec.js +++ b/server/src/server/plugins/ApiSpec.js @@ -12,9 +12,9 @@ describe("server/src/server/plugins/Api", () => { const Console = require('./../../../../client/src/share/Console'); const SConsole = require('./../../share/Console'); const Helper = require('./../../../../common/tests/Helper'); - const Api = require('./Api'); const waitEvent = Helper.waitEvent; const host = Config.serverHost; + const port = SConfig.port; let error; let warn; @@ -29,6 +29,7 @@ describe("server/src/server/plugins/Api", () => { Config.modeNodeJs = true; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; error = Console.error; warn = Console.warn; info = Console.info; @@ -54,6 +55,7 @@ describe("server/src/server/plugins/Api", () => { Config.modeNodeJs = OLD_MODE; Config.serverHost = host; SConfig.modeDistributed = dist; + SConfig.port = port; }); it("Checking unique id on client connect", (done) => { From ea7b134f6336ac4376cb006b1084aa84e129631d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 20 Dec 2017 23:40:49 +0200 Subject: [PATCH 044/291] fixed tests #13 --- client/src/manager/ManagerSpec.js | 8 +- .../plugins/organisms/dos/OperatorsSpec.js | 142 +++++++++--------- client/src/share/Config.js | 4 +- 3 files changed, 77 insertions(+), 77 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index fb89ed3..a347fdc 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -315,6 +315,7 @@ describe("client/src/manager/Manager", () => { const height = Config.worldHeight; const energy = OConfig.orgStartEnergy; const server = new Server(); + Config.worldHeight = 400; const man1 = new Manager(false); delete Config.organisms; delete Config.status; @@ -346,14 +347,13 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = 0; OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; - Config.worldHeight = 400; OConfig.orgStartEnergy = 10000; World.prototype.getFreePos = () => {return {x: 1, y: 399}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001101000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() } else if (man2.organisms.size === 2) { destroy(); } @@ -379,6 +379,7 @@ describe("client/src/manager/Manager", () => { const height = Config.worldHeight; const energy = OConfig.orgStartEnergy; const server = new Server(); + Config.worldHeight = 400; const man1 = new Manager(false); delete Config.organisms; delete Config.status; @@ -413,14 +414,13 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = 0; OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; - Config.worldHeight = 400; OConfig.orgStartEnergy = 10000; World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001101000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() man1.on(EVENTS.STEP_OUT, () => { expect(doneInc < 3).toBe(true); ++doneInc; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index ab5069f..dff8a13 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -198,25 +198,25 @@ describe("client/src/organism/OperatorsDos", () => { ops.destroy(); }); - it("Checking onNot() method", () => { - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - - expect(ops.onNot(0x041fffff, 0, {}, 1)).toEqual(1); //'v0=!v1'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onNot(0x046fffff, 1, {}, 1)).toEqual(2); //'v1=!v2'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onNot(0x04ffffff, 2, {}, 1)).toEqual(3); //'v3=!v3'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); - }); + // it("Checking onNot() method", () => { + // let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + // + // expect(ops.onNot(0x041fffff, 0, {}, 1)).toEqual(1); //'v0=!v1'; + // expect(ops.vars[0] === 0).toEqual(true); + // expect(ops.vars[1] === 1).toEqual(true); + // expect(ops.vars[2] === 2).toEqual(true); + // expect(ops.vars[3] === 3).toEqual(true); + // expect(ops.onNot(0x046fffff, 1, {}, 1)).toEqual(2); //'v1=!v2'; + // expect(ops.vars[0] === 0).toEqual(true); + // expect(ops.vars[1] === 0).toEqual(true); + // expect(ops.vars[2] === 2).toEqual(true); + // expect(ops.vars[3] === 3).toEqual(true); + // expect(ops.onNot(0x04ffffff, 2, {}, 1)).toEqual(3); //'v3=!v3'; + // expect(ops.vars[0] === 0).toEqual(true); + // expect(ops.vars[1] === 0).toEqual(true); + // expect(ops.vars[2] === 2).toEqual(true); + // expect(ops.vars[3] === 0).toEqual(true); + // }); // // it("Checking onPi() method", () => { // let ops = new OperatorsDos([]); @@ -238,7 +238,7 @@ describe("client/src/organism/OperatorsDos", () => { let obs = new Observer(EVENT_AMOUNT); let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - expect(ops.onLookAt(0x071bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); + expect(ops.onLookAt(0x041bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -248,7 +248,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 7; expect(x === 1 && y === 2).toEqual(true); }); - expect(ops.onLookAt(0x071bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); + expect(ops.onLookAt(0x041bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); expect(ops.vars[0] === 7).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -259,7 +259,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 8; expect(x === 2 && y === 3).toEqual(true); }); - expect(ops.onLookAt(0x076fffff, 1, {}, 1)).toEqual(2);//v1=org.lookAt(v2,v3); + expect(ops.onLookAt(0x046fffff, 1, {}, 1)).toEqual(2);//v1=org.lookAt(v2,v3); expect(ops.vars[0] === 7).toEqual(true); expect(ops.vars[1] === 8).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -270,7 +270,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 9; expect(x === 3 && y === 3).toEqual(true); }); - expect(ops.onLookAt(0x07ffffff, 3, {}, 1)).toEqual(4);//v3=org.lookAt(v3,v3); + expect(ops.onLookAt(0x04ffffff, 3, {}, 1)).toEqual(4);//v3=org.lookAt(v3,v3); expect(ops.vars[0] === 7).toEqual(true); expect(ops.vars[1] === 8).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -290,7 +290,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 3 && y === 5).toEqual(true); }); - expect(ops.onEatLeft(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.eatLeft(v1); + expect(ops.onEatLeft(0x051fffff, 0, org, 1)).toEqual(1); // v0=org.eatLeft(v1); expect(ops.vars[0] === 5).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -310,7 +310,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 4 && y === 6).toEqual(true); }); - expect(ops.onEatLeft(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.eatLeft(v2); + expect(ops.onEatLeft(0x056fffff, 0, org, 1)).toEqual(1); // v1=org.eatLeft(v2); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 5).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -330,7 +330,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 1; expect(x === 2 && y === 4).toEqual(true); }); - expect(ops.onEatLeft(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.eatLeft(v3); + expect(ops.onEatLeft(0x05ffffff, 0, org, 1)).toEqual(1); // v3=org.eatLeft(v3); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -351,7 +351,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 5 && y === 5).toEqual(true); }); - expect(ops.onEatRight(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.eatRight(v1); + expect(ops.onEatRight(0x061fffff, 0, org, 1)).toEqual(1); // v0=org.eatRight(v1); expect(ops.vars[0] === 5).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -371,7 +371,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 6 && y === 6).toEqual(true); }); - expect(ops.onEatRight(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.eatRight(v2); + expect(ops.onEatRight(0x066fffff, 0, org, 1)).toEqual(1); // v1=org.eatRight(v2); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 5).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -391,7 +391,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 1; expect(x === 4 && y === 4).toEqual(true); }); - expect(ops.onEatRight(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.eatRight(v3); + expect(ops.onEatRight(0x06ffffff, 0, org, 1)).toEqual(1); // v3=org.eatRight(v3); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -412,7 +412,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 4 && y === 4).toEqual(true); }); - expect(ops.onEatUp(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.onEatUp(v1); + expect(ops.onEatUp(0x071fffff, 0, org, 1)).toEqual(1); // v0=org.onEatUp(v1); expect(ops.vars[0] === 5).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -422,7 +422,7 @@ describe("client/src/organism/OperatorsDos", () => { obs.clear(); ops.destroy(); }); - it("Checking onEatRight() method 2", () => { + it("Checking onEatUp() method 2", () => { let obs = new Observer(EVENT_AMOUNT); let ops = new OperatorsDos([], [1, 1, 2, 3], obs); let org = {x:5, y:6, energy:0}; @@ -432,7 +432,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 5; expect(x === 5 && y === 5).toEqual(true); }); - expect(ops.onEatUp(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.onEatUp(v2); + expect(ops.onEatUp(0x076fffff, 0, org, 1)).toEqual(1); // v1=org.onEatUp(v2); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 5).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -452,7 +452,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.ret = 1; expect(x === 3 && y === 3).toEqual(true); }); - expect(ops.onEatUp(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.onEatUp(v3); + expect(ops.onEatUp(0x07ffffff, 0, org, 1)).toEqual(1); // v3=org.onEatUp(v3); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -535,7 +535,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); + expect(ops.onStepLeft(0x091fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -556,7 +556,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); + expect(ops.onStepLeft(0x091fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -577,7 +577,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); + expect(ops.onStepLeft(0x096fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -599,7 +599,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); + expect(ops.onStepLeft(0x096fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 0).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -620,7 +620,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); + expect(ops.onStepLeft(0x09ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -641,7 +641,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); }); - expect(ops.onStepLeft(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); + expect(ops.onStepLeft(0x09ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -663,7 +663,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); + expect(ops.onStepRight(0x0a1fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -673,7 +673,7 @@ describe("client/src/organism/OperatorsDos", () => { obs.clear(); ops.destroy(); }); - it("Checking onStepRight() method with no free space on the left", () => { + it("Checking onStepRight() method with no free space on the right", () => { let obs = new Observer(EVENT_AMOUNT); let ops = new OperatorsDos([], [0, 1, 2, 3], obs); let org = {x:3, y:4}; @@ -684,7 +684,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); + expect(ops.onStepRight(0x0a1fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -705,7 +705,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); + expect(ops.onStepRight(0x0a6fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -726,7 +726,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); + expect(ops.onStepRight(0x0a6fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 0).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -747,7 +747,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); + expect(ops.onStepRight(0x0affffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -768,7 +768,7 @@ describe("client/src/organism/OperatorsDos", () => { ret.y = 4; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); }); - expect(ops.onStepRight(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); + expect(ops.onStepRight(0x0affffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -783,17 +783,17 @@ describe("client/src/organism/OperatorsDos", () => { let org = {mem: [1,2,3]}; let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - expect(ops.onFromMem(0x081fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); + expect(ops.onFromMem(0x0d1fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); expect(ops.vars[0] === 3).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onFromMem(0x086fffff, 1, org, 2)).toEqual(2); //v1=org.fromMem(); + expect(ops.onFromMem(0x0d6fffff, 1, org, 2)).toEqual(2); //v1=org.fromMem(); expect(ops.vars[0] === 3).toEqual(true); expect(ops.vars[1] === 2).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onFromMem(0x08ffffff, 2, org, 3)).toEqual(3); //v3=org.fromMem(); + expect(ops.onFromMem(0x0dffffff, 2, org, 3)).toEqual(3); //v3=org.fromMem(); expect(ops.vars[0] === 3).toEqual(true); expect(ops.vars[1] === 2).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -805,7 +805,7 @@ describe("client/src/organism/OperatorsDos", () => { let org = {mem: []}; let ops = new OperatorsDos([], [7, 1, 2, 3], new Observer()); - expect(ops.onFromMem(0x081fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); + expect(ops.onFromMem(0x0d1fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -818,11 +818,11 @@ describe("client/src/organism/OperatorsDos", () => { let org = {mem: []}; let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - expect(ops.onToMem(0x08ffffff, 0, org, 1)).toEqual(1); //'v3 = org.toMem(v3)'); + expect(ops.onToMem(0x0effffff, 0, org, 1)).toEqual(1); //'v3 = org.toMem(v3)'); expect(org.mem[0]).toEqual(3); - expect(ops.onToMem(0x086fffff, 0, org, 1)).toEqual(1); //'v1 = org.toMem(v2)'); + expect(ops.onToMem(0x0e6fffff, 0, org, 1)).toEqual(1); //'v1 = org.toMem(v2)'); expect(org.mem[1]).toEqual(2); - expect(ops.onToMem(0x081fffff, 0, org, 1)).toEqual(1); //'v0 = org.toMem(v1)'); + expect(ops.onToMem(0x0e1fffff, 0, org, 1)).toEqual(1); //'v0 = org.toMem(v1)'); expect(org.mem[2]).toEqual(2); ops.destroy(); @@ -832,17 +832,17 @@ describe("client/src/organism/OperatorsDos", () => { let org = {x: 1, y:2}; let ops = new OperatorsDos([], [0, 7, 2, 3], new Observer()); - expect(ops.onMyX(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.myX(); + expect(ops.onMyX(0x0f1fffff, 0, org, 1)).toEqual(1); // v0=org.myX(); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyX(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.myX(); + expect(ops.onMyX(0x0f6fffff, 0, org, 1)).toEqual(1); // v1=org.myX(); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyX(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.myX(); + expect(ops.onMyX(0x0fffffff, 0, org, 1)).toEqual(1); // v3=org.myX(); expect(ops.vars[0] === 1).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -854,17 +854,17 @@ describe("client/src/organism/OperatorsDos", () => { let org = {x: 1, y:2}; let ops = new OperatorsDos([], [0, 7, 2, 3], new Observer()); - expect(ops.onMyY(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.myY(); + expect(ops.onMyY(0x0f1fffff, 0, org, 1)).toEqual(1); // v0=org.myY(); expect(ops.vars[0] === 2).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyY(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.myY(); + expect(ops.onMyY(0x0f6fffff, 0, org, 1)).toEqual(1); // v1=org.myY(); expect(ops.vars[0] === 2).toEqual(true); expect(ops.vars[1] === 2).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyY(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.myY(); + expect(ops.onMyY(0x0fffffff, 0, org, 1)).toEqual(1); // v3=org.myY(); expect(ops.vars[0] === 2).toEqual(true); expect(ops.vars[1] === 2).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -885,7 +885,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 0 && y === 2).toEqual(true); ret.ret = 0; }); - expect(ops.onCheckLeft(0x081fffff, 0, org)).toEqual(1); // v0=org.onCheckLeft(); + expect(ops.onCheckLeft(0x111fffff, 0, org)).toEqual(1); // v0=org.onCheckLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -896,7 +896,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 0 && y === 2).toEqual(true); ret.ret = 1; }); - expect(ops.onCheckLeft(0x086fffff, 0, org)).toEqual(1); // v1=org.onCheckLeft(); + expect(ops.onCheckLeft(0x116fffff, 0, org)).toEqual(1); // v1=org.onCheckLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -907,7 +907,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 0 && y === 2).toEqual(true); ret.ret = 2; }); - expect(ops.onCheckLeft(0x08ffffff, 0, org)).toEqual(1); // v3=org.onCheckLeft(); + expect(ops.onCheckLeft(0x11ffffff, 0, org)).toEqual(1); // v3=org.onCheckLeft(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -928,7 +928,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 2 && y === 2).toEqual(true); ret.ret = 0; }); - expect(ops.onCheckRight(0x081fffff, 0, org)).toEqual(1); // v0=org.onCheckRight(); + expect(ops.onCheckRight(0x121fffff, 0, org)).toEqual(1); // v0=org.onCheckRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -939,7 +939,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 2 && y === 2).toEqual(true); ret.ret = 1; }); - expect(ops.onCheckRight(0x086fffff, 0, org)).toEqual(1); // v1=org.onCheckRight(); + expect(ops.onCheckRight(0x126fffff, 0, org)).toEqual(1); // v1=org.onCheckRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -950,7 +950,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 2 && y === 2).toEqual(true); ret.ret = 2; }); - expect(ops.onCheckRight(0x08ffffff, 0, org)).toEqual(1); // v3=org.onCheckRight(); + expect(ops.onCheckRight(0x12ffffff, 0, org)).toEqual(1); // v3=org.onCheckRight(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -971,7 +971,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 1).toEqual(true); ret.ret = 0; }); - expect(ops.onCheckUp(0x081fffff, 0, org)).toEqual(1); // v0=org.onCheckUp(); + expect(ops.onCheckUp(0x131fffff, 0, org)).toEqual(1); // v0=org.onCheckUp(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -982,7 +982,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 1).toEqual(true); ret.ret = 1; }); - expect(ops.onCheckUp(0x086fffff, 0, org)).toEqual(1); // v1=org.onCheckUp(); + expect(ops.onCheckUp(0x136fffff, 0, org)).toEqual(1); // v1=org.onCheckUp(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -993,7 +993,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 1).toEqual(true); ret.ret = 2; }); - expect(ops.onCheckUp(0x08ffffff, 0, org)).toEqual(1); // v3=org.onCheckUp(); + expect(ops.onCheckUp(0x13ffffff, 0, org)).toEqual(1); // v3=org.onCheckUp(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -1014,7 +1014,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 3).toEqual(true); ret.ret = 0; }); - expect(ops.onCheckDown(0x081fffff, 0, org)).toEqual(1); // v0=org.onCheckDown(); + expect(ops.onCheckDown(0x141fffff, 0, org)).toEqual(1); // v0=org.onCheckDown(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 7).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -1025,7 +1025,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 3).toEqual(true); ret.ret = 1; }); - expect(ops.onCheckDown(0x086fffff, 0, org)).toEqual(1); // v1=org.onCheckDown(); + expect(ops.onCheckDown(0x146fffff, 0, org)).toEqual(1); // v1=org.onCheckDown(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); @@ -1036,7 +1036,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(x === 1 && y === 3).toEqual(true); ret.ret = 2; }); - expect(ops.onCheckDown(0x08ffffff, 0, org)).toEqual(1); // v3=org.onCheckDown(); + expect(ops.onCheckDown(0x14ffffff, 0, org)).toEqual(1); // v3=org.onCheckDown(); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 1).toEqual(true); expect(ops.vars[2] === 2).toEqual(true); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 02f5cd3..d177ac2 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -52,8 +52,8 @@ ClientConfig.init({ /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 - * size and the organism has 10x5 position in it, one step right will move - * this organism at the position 1x5. The same scenario regarding Y + * size and the organism has 9x5 position in it, one step right will move + * this organism at the position 0x5. The same scenario regarding Y * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ From f3d53afdde8d70645d911917c67f010bdb4b93e6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 09:21:29 +0200 Subject: [PATCH 045/291] test commit to fix travis CI fails --- client/src/share/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/share/Config.js b/client/src/share/Config.js index d177ac2..26a19a2 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -97,7 +97,7 @@ ClientConfig.init({ /** * {Number} Port number for connecting with server */ - serverPort: 8200, + serverPort: 8099, /** * {String} Host for connecting with server */ From d676c531392c400eeb769ed94892f0bf4a3bbd49 Mon Sep 17 00:00:00 2001 From: tmptrash Date: Thu, 21 Dec 2017 16:45:26 +0200 Subject: [PATCH 046/291] fixed issue with turned off messages in Status plugin --- client/src/manager/plugins/status/Status.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 3281e7f..a3a2be8 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -61,16 +61,17 @@ class Status extends Configurable { this._onAfterIps(stamp); } + _onOrganism(org, lines) { + if (!StatusConfig.showMessages) {return} + this._runLines += lines; + } + _format(value, name, orgs, fixed, pad, coef = 1, lines = true, perOrg = true) { orgs = perOrg ? orgs : 1; lines = lines ? this._runLines : 1; return `${name}:${(((value / orgs) / lines) * coef).toFixed(fixed)}`.padEnd(pad); } - _onOrganism(org, lines) { - this._runLines += lines; - } - _onBeforeIps(ips, orgs) { let item = orgs.first; let energy = 0; From 4a8e43657164ca3d96545a60801a5be3c5fecd5a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 22:48:55 +0200 Subject: [PATCH 047/291] alternative variant of Status logs #93 --- .../src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/status/Status.js | 144 +++++++++--------- client/src/share/Config.js | 2 +- 3 files changed, 76 insertions(+), 72 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 0059f4f..afec406 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -127,7 +127,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 50, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index a3a2be8..5e1091c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -1,5 +1,17 @@ /** - * Shows console status of application + * This plugin is a primitive version of real time charts. It shows + * different parameters of the jevo.js system, like average energy, + * iq (energy picking speed), average code size and so on. Here labels + * explanation: + * ips: Iterations Per Second - amount of all organisms full code + * runs per one second + * lps: Lines Per Second - average run code lines per second + * org: Average amount of organisms + * nrg: Amount of energy of average organism + * iq : Energy picking speed per time + * che: Average changes amount + * fit: Fitness of one average organism + * cod: Average code size * * @author flatline */ @@ -12,110 +24,102 @@ const GREEN = 'color: #00aa00'; const RED = 'color: #aa0000'; class Status extends Configurable { + static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = true) { + orgs = perOrg ? orgs : 1; + return `${name}:${((value / orgs) * coef).toFixed(fixed)}`.padEnd(pad); + } + constructor(manager) { super(manager, {Config, cfg: StatusConfig}); - this._manager = manager; - this._stamp = 0; - this._ips = 0; - this._energy = 0; - this._codeSize = 0; - this._runLines = 1; - this._times = 0; - this._oldValues = [0, 0, 0]; - this._speed = [0, 0, 0]; - - manager.on(EVENTS.IPS, this._onIps.bind(this)); - manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); + this._manager = manager; + this._stamp = 0; + this._curEnergy = 0; + this._energy = 0; + this._fitness = 0; + this._changes = 0; + this._codeSize = 0; + this._runLines = 1; + this._times = 0; + this._ipsTimes = 0; + this._oldValues = [0, 0]; + this._onIpsCb = this._onIps.bind(this); + this._onOrganismCb = this._onOrganism.bind(this); + + manager.on(EVENTS.IPS, this._onIpsCb); + manager.on(EVENTS.ORGANISM, this._onOrganismCb); } destroy() { - this._manager = null; - this._oldValues = null; - this._speed = null; + this._manager.off(EVENTS.IPS, this._onIpsCb); + this._manager.off(EVENTS.ORGANISM, this._onOrganismCb); + this._onIpsCb = null; + this._onOrganismCb = null; + this._manager = null; + this._oldValues = null; super.destroy(); } _onIps(ips, orgs) { if (!StatusConfig.showMessages) {return} const stamp = Date.now(); - - this._onBeforeIps(ips, orgs); + this._ipsTimes++; if (stamp - this._stamp < StatusConfig.period) {return} - const times = this._times || 1; - const times1 = (times - 1) || 1; - const realIps = this._ips / times; + this._onBeforeLog(ips, orgs); + const format = Status._format; + const times = this._times; const orgAmount = orgs.size || 1; - const sips = `ips:${realIps.toFixed(realIps < 10 ? 2 : 0)}`.padEnd(10); - const slps = this._format(this._runLines / times, 'lps', orgAmount, 0, 14, 1, false, false); - const sorgs = this._format(orgAmount, 'org', orgAmount, 0, 10, 1, false, false); - const senergy = this._format(this._energy / times, 'nrg', orgAmount, 0, 14, 1, false); - const siq = this._format(this._speed[0] / times1, 'iq', orgAmount, 3, 13, 1000); - const schanges = this._format(this._speed[1] / times1, 'che', orgAmount, 3, 12, 100000); - const sfit = this._format(this._speed[2] / times1, 'fit', orgAmount, 3, 14); - const scode = this._format(this._codeSize / times, 'cod', orgAmount, 1, 12, 1, false); + const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); + const slps = format(this._runLines / this._ipsTimes, 'lps', orgAmount, 0, 14, 1, false); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10, 1, false); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14, 1, false); + const siq = format(this._energy / times, 'iq', orgAmount, 3, 13, 0.001, false); + const sfit = format(this._fitness / times, 'fit', orgAmount, 3, 14, 0.000001, false); + const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1); + const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); this._manager.hasView && this._manager.canvas.text(5, 15, sips); - this._onAfterIps(stamp); + this._onAfterLog(stamp); } _onOrganism(org, lines) { if (!StatusConfig.showMessages) {return} this._runLines += lines; } - - _format(value, name, orgs, fixed, pad, coef = 1, lines = true, perOrg = true) { - orgs = perOrg ? orgs : 1; - lines = lines ? this._runLines : 1; - return `${name}:${(((value / orgs) / lines) * coef).toFixed(fixed)}`.padEnd(pad); - } - _onBeforeIps(ips, orgs) { - let item = orgs.first; - let energy = 0; - let codeSize = 0; - let changes = 0; - let fitness = 0; - let org; + _onBeforeLog(ips, orgs) { + const olds = this._oldValues; + const size = orgs.size || 1; + let energy = 0; + let fitness = 0; + let changes = 0; + let codeSize = 0; + let item = orgs.first; + let org; while(item && (org = item.val)) { energy += org.energy; - codeSize += org.vm.size; changes += org.changes; fitness += org.fitness(); - item = item.next; - } - - if (this._oldValues) { - const olds = this._oldValues; - this._speed[0] += energy - olds[0]; - this._speed[1] += changes - olds[1]; - this._speed[2] += fitness - olds[2]; + codeSize += org.vm.size; + item = item.next; } - this._ips += ips; - this._energy += energy; - this._codeSize += codeSize; - this._setOldValues(energy, changes, fitness); - + this._curEnergy = (energy /= size); + this._energy += (energy - olds[0]); + this._fitness += ((fitness /= size) - olds[1]); + this._changes = changes; + this._codeSize = codeSize; + this._oldValues = [energy, fitness]; this._times++; } - _onAfterIps(stamp) { - this._ips = 0; - this._energy = 0; - this._codeSize = 0; - this._runLines = 0; - this._times = 0; - this._stamp = stamp; - this._oldValues = null; - this._speed = [0, 0, 0]; - } - - _setOldValues(energy, changes, fitness) { - this._oldValues = [energy, changes, fitness]; + _onAfterLog(stamp) { + this._ipsTimes = 0; + this._runLines = 0; + this._stamp = stamp; } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 26a19a2..cd92a9c 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... From 224ee782ce58b9dc938d86a2043d054713e7d0d8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 23:04:22 +0200 Subject: [PATCH 048/291] implemented simple logic in Status log #93 --- client/src/manager/plugins/status/Status.js | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 5e1091c..68cf8f6 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -24,8 +24,8 @@ const GREEN = 'color: #00aa00'; const RED = 'color: #aa0000'; class Status extends Configurable { - static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = true) { - orgs = perOrg ? orgs : 1; + static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = false) { + orgs = perOrg ? orgs : 1; return `${name}:${((value / orgs) * coef).toFixed(fixed)}`.padEnd(pad); } @@ -71,13 +71,13 @@ class Status extends Configurable { const times = this._times; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._ipsTimes, 'lps', orgAmount, 0, 14, 1, false); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10, 1, false); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14, 1, false); - const siq = format(this._energy / times, 'iq', orgAmount, 3, 13, 0.001, false); - const sfit = format(this._fitness / times, 'fit', orgAmount, 3, 14, 0.000001, false); - const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1); - const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1); + const slps = format(this._runLines / this._ipsTimes, 'lps', orgAmount, 0, 14, 1 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10, 1 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14, 1 ); + const siq = format(this._energy / times, 'iq', orgAmount, 3, 13, 0.001 ); + const sfit = format(this._fitness / times, 'fit', orgAmount, 3, 14, 0.000001); + const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true ); + const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true ); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); this._manager.hasView && this._manager.canvas.text(5, 15, sips); @@ -108,8 +108,8 @@ class Status extends Configurable { } this._curEnergy = (energy /= size); - this._energy += (energy - olds[0]); - this._fitness += ((fitness /= size) - olds[1]); + this._energy = (energy - olds[0]); + this._fitness = ((fitness /= size) - olds[1]); this._changes = changes; this._codeSize = codeSize; this._oldValues = [energy, fitness]; From 3ad03108ddb4fa6245de1f9327e256f77b308e97 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 23:42:29 +0200 Subject: [PATCH 049/291] hope last version of Status calculations #93 --- client/src/manager/plugins/status/Status.js | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 68cf8f6..307daae 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -41,7 +41,6 @@ class Status extends Configurable { this._codeSize = 0; this._runLines = 1; this._times = 0; - this._ipsTimes = 0; this._oldValues = [0, 0]; this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); @@ -63,21 +62,20 @@ class Status extends Configurable { _onIps(ips, orgs) { if (!StatusConfig.showMessages) {return} const stamp = Date.now(); - this._ipsTimes++; + this._times++; if (stamp - this._stamp < StatusConfig.period) {return} this._onBeforeLog(ips, orgs); const format = Status._format; - const times = this._times; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._ipsTimes, 'lps', orgAmount, 0, 14, 1 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10, 1 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14, 1 ); - const siq = format(this._energy / times, 'iq', orgAmount, 3, 13, 0.001 ); - const sfit = format(this._fitness / times, 'fit', orgAmount, 3, 14, 0.000001); - const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true ); - const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true ); + const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 13, 1000 ); + const sfit = format(this._fitness, 'fit', orgAmount, 3, 14 ); + const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true); + const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); this._manager.hasView && this._manager.canvas.text(5, 15, sips); @@ -92,6 +90,7 @@ class Status extends Configurable { _onBeforeLog(ips, orgs) { const olds = this._oldValues; const size = orgs.size || 1; + const lines = this._runLines; let energy = 0; let fitness = 0; let changes = 0; @@ -107,17 +106,18 @@ class Status extends Configurable { item = item.next; } - this._curEnergy = (energy /= size); - this._energy = (energy - olds[0]); - this._fitness = ((fitness /= size) - olds[1]); + this._curEnergy = energy / size; + energy = (energy / size) / lines; + fitness = (fitness / size) / lines; + this._energy = energy - olds[0]; + this._fitness = fitness - olds[1]; this._changes = changes; this._codeSize = codeSize; this._oldValues = [energy, fitness]; - this._times++; } _onAfterLog(stamp) { - this._ipsTimes = 0; + this._times = 0; this._runLines = 0; this._stamp = stamp; } From 34670dc792ad8c82143281b3e19b2e4e499f51d6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 23:51:23 +0200 Subject: [PATCH 050/291] one more fix of Status logging logic #93 --- client/src/manager/plugins/status/Status.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 307daae..8f72832 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -106,11 +106,11 @@ class Status extends Configurable { item = item.next; } - this._curEnergy = energy / size; - energy = (energy / size) / lines; - fitness = (fitness / size) / lines; - this._energy = energy - olds[0]; - this._fitness = fitness - olds[1]; + energy /= size; + fitness /= size; + this._curEnergy = energy; + this._energy = (energy - olds[0]) / lines; + this._fitness = (fitness - olds[1]) / lines; this._changes = changes; this._codeSize = codeSize; this._oldValues = [energy, fitness]; From 315dd201e61f1b29a081a9357eec638331cb19b9 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 21 Dec 2017 23:55:42 +0200 Subject: [PATCH 051/291] fixed comments #93 --- client/src/manager/plugins/status/Status.js | 24 +++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 8f72832..f848d20 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -1,17 +1,19 @@ /** * This plugin is a primitive version of real time charts. It shows * different parameters of the jevo.js system, like average energy, - * iq (energy picking speed), average code size and so on. Here labels - * explanation: - * ips: Iterations Per Second - amount of all organisms full code - * runs per one second - * lps: Lines Per Second - average run code lines per second - * org: Average amount of organisms - * nrg: Amount of energy of average organism - * iq : Energy picking speed per time - * che: Average changes amount - * fit: Fitness of one average organism - * cod: Average code size + * iq (energy picking speed), average code size and so on. Here + * labels explanation: + * + * ips: Iterations Per Second - amount of all organisms full + * code runs per one second + * lps: Lines Per Second - average amount of run code lines + * per one second + * org: Average amount of organisms at the moment of logging + * nrg: Amount of energy of average organism + * iq : Energy picking speed per StatusConfig.period seconds + * che: Changes amount of average organism + * fit: Fitness of average organism + * cod: Code size of average organism * * @author flatline */ From 8a0838cdd9294546105072de8652cc3b482432a4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 22 Dec 2017 01:08:49 +0200 Subject: [PATCH 052/291] fixed issue with one organism on the world --- client/src/manager/plugins/organisms/dos/Organisms.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 8127c56..e0afe2c 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -64,6 +64,14 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { let energy = (((org.energy * org.cloneEnergyPercent) + 0.5) << 1) >>> 1; // analog of Math.round() + // + // This is vary special case, when organisms cheating by creating + // ancestors and put all energy into them at the same time resetting + // their iterations property and make them immortal + // + if (energy === org.energy) { + energy--; + } org.grabEnergy(energy); child.grabEnergy(child.energy - energy); } From cccb816b29ef7e6ae6a73b1618439b0c56ce97bd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 22 Dec 2017 01:09:47 +0200 Subject: [PATCH 053/291] merge... --- client/src/manager/plugins/organisms/dos/Organisms.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 8127c56..e0afe2c 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -64,6 +64,14 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { let energy = (((org.energy * org.cloneEnergyPercent) + 0.5) << 1) >>> 1; // analog of Math.round() + // + // This is vary special case, when organisms cheating by creating + // ancestors and put all energy into them at the same time resetting + // their iterations property and make them immortal + // + if (energy === org.energy) { + energy--; + } org.grabEnergy(energy); child.grabEnergy(child.energy - energy); } From 2172c800c46d72ba30fb99d5d28bc2e5339f338c Mon Sep 17 00:00:00 2001 From: tmptrash Date: Fri, 22 Dec 2017 12:17:13 +0200 Subject: [PATCH 054/291] added error handlers for sending and closing connection actions #93 --- common/src/net/Client.js | 1 + common/src/plugins/Request.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/common/src/net/Client.js b/common/src/net/Client.js index f8402aa..09fa608 100644 --- a/common/src/net/Client.js +++ b/common/src/net/Client.js @@ -83,6 +83,7 @@ class Client extends Connection { try { client = new WS(`${this.host}:${this.port}`); + client.on('error', (e) => this.fire(this.EVENTS.ERR, e)); } catch (e) { this.fire(this.EVENTS.ERR, e.message); } diff --git a/common/src/plugins/Request.js b/common/src/plugins/Request.js index 6edbf28..b340cde 100644 --- a/common/src/plugins/Request.js +++ b/common/src/plugins/Request.js @@ -74,8 +74,11 @@ class Request { const reqId = Helper.getId(); cb && (this._requests[reqId] = cb); - sock.send(JSON.stringify([type, (reqId | MASKS.REQ_MASK) >>> 0].concat(params)), this._onSendErrCb); - + try { + sock.send(JSON.stringify([type, (reqId | MASKS.REQ_MASK) >>> 0].concat(params)), this._onSendErrCb); + } catch (e) { + this._onSendErr(e); + } return reqId; } @@ -90,7 +93,11 @@ class Request { * @override */ _onResponse(sock, type, reqId, ...params) { - sock.send(JSON.stringify([type, (reqId & MASKS.RES_MASK) >>> 0].concat(params)), this._onSendErrCb); + try { + sock.send(JSON.stringify([type, (reqId & MASKS.RES_MASK) >>> 0].concat(params)), this._onSendErrCb); + } catch (e) { + this._onSendErr(e); + } } /** From 0702be85a23de955740b5a85dc44035b61dd67c8 Mon Sep 17 00:00:00 2001 From: tmptrash Date: Fri, 22 Dec 2017 12:49:43 +0200 Subject: [PATCH 055/291] tabs -> spaces --- common/src/net/Client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/net/Client.js b/common/src/net/Client.js index 09fa608..eee5b5f 100644 --- a/common/src/net/Client.js +++ b/common/src/net/Client.js @@ -83,7 +83,7 @@ class Client extends Connection { try { client = new WS(`${this.host}:${this.port}`); - client.on('error', (e) => this.fire(this.EVENTS.ERR, e)); + client.on('error', (e) => this.fire(this.EVENTS.ERR, e)); } catch (e) { this.fire(this.EVENTS.ERR, e.message); } From ff3b8a46aae9417c1361cb7c7e72bad638a67579 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 22 Dec 2017 23:51:16 +0200 Subject: [PATCH 056/291] fixed an issue with immortal organisms --- client/src/manager/plugins/organisms/Organism.js | 3 ++- client/src/manager/plugins/organisms/dos/Organisms.js | 8 -------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 9e22b64..5f5b248 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -58,7 +58,6 @@ class Organism extends Observer { this._changes = 1; this._alive = alive; this._item = item; - this._iterations = 0; this._fnId = 0; } @@ -196,6 +195,7 @@ class Organism extends Observer { this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; + this._iterations = 0; this._mem = []; } @@ -208,6 +208,7 @@ class Organism extends Observer { this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; this._cloneEnergyPercent = parent.cloneEnergyPercent; + this._iterations = parent.iterations; this._mem = parent.mem.slice(); } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index e0afe2c..8127c56 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -64,14 +64,6 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { let energy = (((org.energy * org.cloneEnergyPercent) + 0.5) << 1) >>> 1; // analog of Math.round() - // - // This is vary special case, when organisms cheating by creating - // ancestors and put all energy into them at the same time resetting - // their iterations property and make them immortal - // - if (energy === org.energy) { - energy--; - } org.grabEnergy(energy); child.grabEnergy(child.energy - energy); } From 4f45a034ba0283f649b9da1c2822d105b2cdcc40 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 23 Dec 2017 00:54:48 +0200 Subject: [PATCH 057/291] VM speed optimizations fixed VM.linesRun property #96 --- .../src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/status/Status.js | 2 +- client/src/share/Config.js | 4 ++-- client/src/vm/VM.js | 23 ++++++++----------- server/src/share/Config.js | 8 +++---- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index afec406..c1c5aa6 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -127,7 +127,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 50, + orgMaxOrgs: 200, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index f848d20..2b190bd 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -74,7 +74,7 @@ class Status extends Configurable { const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 13, 1000 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 13, 100000 ); const sfit = format(this._fitness, 'fit', orgAmount, 3, 14 ); const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true); const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index cd92a9c..bbe468e 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -97,7 +97,7 @@ ClientConfig.init({ /** * {Number} Port number for connecting with server */ - serverPort: 8099, + serverPort: 8301, /** * {String} Host for connecting with server */ diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 82ac711..4b616f7 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -61,7 +61,6 @@ class VM extends Observer { this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; this._line = 0; - this._linesRun = 0; } get code() {return this._code} @@ -108,27 +107,25 @@ class VM extends Observer { while (len-- > 0 && org.alive) { line = ops[code[line] >>> VAR_BITS_OFFS](code[line], line, org, lines, ret); // + // We reach the end of the script and have to run it from the beginning + // + if (line >= lines && org.alive) { + line = 0; + this._operators.offsets = this._offsets = []; + this._onCodeEnd(len2 - len - 1); + continue; + } + // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) // if ((ret = (offs.length > 0 && line === offs[offs.length - 1]))) { offs.pop(); line = offs.pop(); - continue; - } - if (line >= lines) { - if (org.alive) { - line = 0; - this._operators.offsets = this._offsets = []; - this._onCodeEnd(this._linesRun + (len2 - len)); - this._linesRun = -(len2 - len); - } - break; } } - this._linesRun += (len2 - len); - this._line = line; + this._line = line; } destroy() { diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 83e564d..32cd12b 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -31,12 +31,12 @@ ServerConfig.init({ * with additional "around" rows and columns for connecting with sibling * servers. So, result amount of cells will be e.g.: 16 + 2 rows + 2 cols. */ - maxConnections: 1, + maxConnections: 4, /** * {Number} Port number for connecting with server. This value will be * passed to the server during creation */ - port: 8201, + port: 8301, /** * {Boolean} Means, that this server will be run in distributed mode. And * will be connected with near servers (up...left). false, means, that @@ -46,11 +46,11 @@ ServerConfig.init({ /** * {String} Host address of server above. Shouldn't contain port */ - upHost: 'ws://127.0.0.1', + upHost: 'ws://192.168.31.176', /** * {Number} Port number of server above. */ - upPort: 8110, + upPort: 8201, /** * {String} Host address of server on the right. Shouldn't contain port */ From db0550cb034ef96aa39121f1451a2b9797e0b32f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 23 Dec 2017 11:29:29 +0200 Subject: [PATCH 058/291] fixed few small issues in VM related to amount of run lines #96 --- client/src/manager/plugins/organisms/Organism.js | 4 ++-- client/src/vm/VM.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 5f5b248..47e80d5 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -187,7 +187,7 @@ class Organism extends Observer { } _create() { - this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls); + this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._color = OConfig.orgStartColor; this._mutationProbs = OConfig.orgMutationProbs.slice(); @@ -200,7 +200,7 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls, parent.vm); + this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls, parent.vm); this._energy = parent.energy; this._color = parent.color; this._mutationProbs = parent.mutationProbs.slice(); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 4b616f7..f46f808 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -99,7 +99,7 @@ class VM extends Observer { const lines = code.length; const ops = this._ops; const offs = this._offsets; - const len2 = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; + let len2 = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; let len = len2; let line = this._line; let ret = false; @@ -112,7 +112,8 @@ class VM extends Observer { if (line >= lines && org.alive) { line = 0; this._operators.offsets = this._offsets = []; - this._onCodeEnd(len2 - len - 1); + this._onCodeEnd(len2 - len); + len2 = len; continue; } // From c78b5e0645359d479fa88ce28fff1cf604892392 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 23 Dec 2017 15:33:31 +0200 Subject: [PATCH 059/291] just sync between computers... --- client/src/manager/ManagerSpec.js | 131 +++++++++++++++++++++++++----- 1 file changed, 110 insertions(+), 21 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index a347fdc..dd15193 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -1,4 +1,5 @@ describe("client/src/manager/Manager", () => { + const SERVER_HOST = 'ws://127.0.0.1'; const Config = require('./../../../client/src/share/Config').Config; const OConfig = require('./../manager/plugins/organisms/Config'); const SConfig = require('./../../../server/src/share/Config').Config; @@ -37,7 +38,7 @@ describe("client/src/manager/Manager", () => { }); beforeAll(() => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; - Config.serverHost = 'ws://127.0.0.1'; + Config.serverHost = SERVER_HOST; Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); Config.modeNodeJs = true; dist = SConfig.modeDistributed; @@ -46,28 +47,28 @@ describe("client/src/manager/Manager", () => { SConfig.maxConnections = 100; OConfig.orgStartAmount = 0; - error = Console.error; - warn = Console.warn; - info = Console.info; - Console.error = emptyFn; - Console.warn = emptyFn; - Console.info = emptyFn; - - serror = SConsole.error; - swarn = SConsole.warn; - sinfo = SConsole.info; - SConsole.error = emptyFn; - SConsole.warn = emptyFn; - SConsole.info = emptyFn; + // error = Console.error; + // warn = Console.warn; + // info = Console.info; + // Console.error = emptyFn; + // Console.warn = emptyFn; + // Console.info = emptyFn; + // + // serror = SConsole.error; + // swarn = SConsole.warn; + // sinfo = SConsole.info; + // SConsole.error = emptyFn; + // SConsole.warn = emptyFn; + // SConsole.info = emptyFn; }); afterAll(() => { - SConsole.error = serror; - SConsole.warn = swarn; - SConsole.info = sinfo; - - Console.error = error; - Console.warn = warn; - Console.info = info; + // SConsole.error = serror; + // SConsole.warn = swarn; + // SConsole.info = sinfo; + // + // Console.error = error; + // Console.warn = warn; + // Console.info = info; Config.modeNodeJs = OLD_MODE; Config.plugIncluded.push('ips/Ips'); jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; @@ -584,4 +585,92 @@ describe("client/src/manager/Manager", () => { man2.run(() => ++count === 2 && (waitObj.done = true)); wait(waitObj, cb); }); + + // it('Tests organism moving from client of one server to client of other server', () => { + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const period1 = OConfig.orgEnergySpendPeriod; + // const clone = OConfig.orgClonePeriod; + // const energy = OConfig.orgStartEnergy; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // const cport = Config.serverPort; + // const chost = Config.serverHost; + // const cycl = Config.worldCyclical; + // const sport = SConfig.port; + // const sdport = SConfig.downPort; + // const suport = SConfig.upPort; + // const maxConns = SConfig.maxConnections; + // const freePos = World.prototype.getFreePos; + // let iterated1 = 0; + // let iterated2 = 0; + // let org1 = null; + // const destroy = () => { + // man1.destroy(() => { + // man2.destroy(() => { + // waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + // World.prototype.getFreePos = freePos; + // OConfig.orgStartEnergy = energy; + // OConfig.orgClonePeriod = clone; + // OConfig.orgEnergySpendPeriod = period1; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // Config.worldWidth = width; + // Config.worldHeight = height; + // SConfig.port = sport; + // SConfig.downPort = sdport; + // SConfig.upPort = suport; + // Config.serverPort = cport; + // Config.serverHost = chost; + // SConfig.maxConnections = maxConns; + // Config.worldCyclical = cycl; + // done(); + // }); + // }); + // }); + // }; + // + // SConfig.maxConnections = 1; + // SConfig.port = 3000; + // SConfig.downPort = 3001; + // const server1 = new Server(); // up server + // SConfig.port = 3001; + // SConfig.upPort = 3000; + // const server2 = new Server(); // down server + // Config.worldWidth = 10; + // Config.worldHeight = 10; + // Config.serverPort = 3000; + // Config.serverHost = SERVER_HOST; + // const man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // Config.serverPort = 3001; + // const man2 = new Manager(false); + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgEnergySpendPeriod = 0; + // OConfig.orgClonePeriod = 0; + // OConfig.orgStartEnergy = 10000; + // Config.worldCyclical = false; + // World.prototype.getFreePos = () => {return {x: 1, y: 9}}; + // + // man1.on(EVENTS.ITERATION, () => { + // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + // org1 = man1.organisms.first.val; + // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + // } else if (man2.organisms.size === 2) { + // destroy(); + // } + // if (iterated1 > 10000) {throw 'Error sending organism between Servers'} + // iterated1++; + // }); + // man2.on(EVENTS.ITERATION, () => iterated2++); + // + // server1.run(); + // server2.run(); + // man1.run(man2.run); + // }); }); \ No newline at end of file From ccfc76e7bbba47d4427ed855a5e832de0c02fcb8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 23 Dec 2017 15:52:10 +0200 Subject: [PATCH 060/291] sync... --- client/src/manager/ManagerSpec.js | 177 +++++++++++++++--------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index dd15193..6a564ad 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -586,91 +586,94 @@ describe("client/src/manager/Manager", () => { wait(waitObj, cb); }); - // it('Tests organism moving from client of one server to client of other server', () => { - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const period1 = OConfig.orgEnergySpendPeriod; - // const clone = OConfig.orgClonePeriod; - // const energy = OConfig.orgStartEnergy; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // const cport = Config.serverPort; - // const chost = Config.serverHost; - // const cycl = Config.worldCyclical; - // const sport = SConfig.port; - // const sdport = SConfig.downPort; - // const suport = SConfig.upPort; - // const maxConns = SConfig.maxConnections; - // const freePos = World.prototype.getFreePos; - // let iterated1 = 0; - // let iterated2 = 0; - // let org1 = null; - // const destroy = () => { - // man1.destroy(() => { - // man2.destroy(() => { - // waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - // World.prototype.getFreePos = freePos; - // OConfig.orgStartEnergy = energy; - // OConfig.orgClonePeriod = clone; - // OConfig.orgEnergySpendPeriod = period1; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // Config.worldWidth = width; - // Config.worldHeight = height; - // SConfig.port = sport; - // SConfig.downPort = sdport; - // SConfig.upPort = suport; - // Config.serverPort = cport; - // Config.serverHost = chost; - // SConfig.maxConnections = maxConns; - // Config.worldCyclical = cycl; - // done(); - // }); - // }); - // }); - // }; - // - // SConfig.maxConnections = 1; - // SConfig.port = 3000; - // SConfig.downPort = 3001; - // const server1 = new Server(); // up server - // SConfig.port = 3001; - // SConfig.upPort = 3000; - // const server2 = new Server(); // down server - // Config.worldWidth = 10; - // Config.worldHeight = 10; - // Config.serverPort = 3000; - // Config.serverHost = SERVER_HOST; - // const man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // Config.serverPort = 3001; - // const man2 = new Manager(false); - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgEnergySpendPeriod = 0; - // OConfig.orgClonePeriod = 0; - // OConfig.orgStartEnergy = 10000; - // Config.worldCyclical = false; - // World.prototype.getFreePos = () => {return {x: 1, y: 9}}; - // - // man1.on(EVENTS.ITERATION, () => { - // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - // org1 = man1.organisms.first.val; - // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - // } else if (man2.organisms.size === 2) { - // destroy(); - // } - // if (iterated1 > 10000) {throw 'Error sending organism between Servers'} - // iterated1++; - // }); - // man2.on(EVENTS.ITERATION, () => iterated2++); - // - // server1.run(); - // server2.run(); - // man1.run(man2.run); - // }); + it('Tests organism moving from client of one server to client of other server', () => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const clone = OConfig.orgClonePeriod; + const energy = OConfig.orgStartEnergy; + const width = Config.worldWidth; + const height = Config.worldHeight; + const cport = Config.serverPort; + const chost = Config.serverHost; + const cycl = Config.worldCyclical; + const sport = SConfig.port; + const sdport = SConfig.downPort; + const suport = SConfig.upPort; + const maxConns = SConfig.maxConnections; + const distrib = SConfig.modeDistributed; + const freePos = World.prototype.getFreePos; + let iterated1 = 0; + let iterated2 = 0; + let org1 = null; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgClonePeriod = clone; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldWidth = width; + Config.worldHeight = height; + SConfig.port = sport; + SConfig.downPort = sdport; + SConfig.upPort = suport; + Config.serverPort = cport; + Config.serverHost = chost; + SConfig.maxConnections = maxConns; + Config.worldCyclical = cycl; + SConfig.modeDistributed = distrib; + done(); + }); + }); + }); + }; + + SConfig.modeDistributed = true; + SConfig.maxConnections = 1; + SConfig.port = 3000; + SConfig.downPort = 3001; + const server1 = new Server(); // up server + SConfig.port = 3001; + SConfig.upPort = 3000; + const server2 = new Server(); // down server + Config.worldWidth = 10; + Config.worldHeight = 10; + Config.serverPort = 3000; + Config.serverHost = SERVER_HOST; + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + Config.serverPort = 3001; + const man2 = new Manager(false); + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgClonePeriod = 0; + OConfig.orgStartEnergy = 10000; + Config.worldCyclical = false; + World.prototype.getFreePos = () => {return {x: 1, y: 9}}; + + man1.on(EVENTS.ITERATION, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + } else if (man2.organisms.size === 2) { + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Servers'} + iterated1++; + }); + man2.on(EVENTS.ITERATION, () => iterated2++); + + server1.run(); + server2.run(); + man1.run(man2.run); + }); }); \ No newline at end of file From 71afd445753a22aaa6d4908deeaab2d80d20e6ac Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 24 Dec 2017 00:31:42 +0200 Subject: [PATCH 061/291] sync... --- client/src/manager/ManagerSpec.js | 1045 +++++++++++++++-------------- server/src/server/plugins/Api.js | 2 - 2 files changed, 534 insertions(+), 513 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 6a564ad..c82ee35 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -20,6 +20,7 @@ describe("client/src/manager/Manager", () => { const port = SConfig.port; const maxConns = SConfig.maxConnections; const startOrgs = OConfig.orgStartAmount; + const energyCheck = Config.worldEnergyCheckPeriod; let error; let warn; @@ -46,6 +47,7 @@ describe("client/src/manager/Manager", () => { SConfig.port = Config.serverPort; SConfig.maxConnections = 100; OConfig.orgStartAmount = 0; + Config.worldEnergyCheckPeriod = 0; // error = Console.error; // warn = Console.warn; @@ -77,516 +79,519 @@ describe("client/src/manager/Manager", () => { SConfig.port = port; SConfig.maxConnections = maxConns; OConfig.orgStartAmount = startOrgs; + Config.worldEnergyCheckPeriod = energyCheck; }); - it("Checking manager creation", (done) => { - const man = new Manager(false); - expect(man.canvas).toBe(null); - man.destroy(done); - }); - it("Checking manager creation and it's properties", (done) => { - const man = new Manager(false); - expect(man.organisms.size).toBe(0); - expect(Object.keys(man.positions).length).toBe(0); - expect(man.codeRuns).toBe(0); - expect(!!man.api.version).toBe(true); - expect(man.api.visualize).toBe(undefined); - expect(man.active).toBe(false); - expect(man.clientId).toBe(null); - expect(man.isDistributed()).toBe(false); - expect(man.hasView).toBe(false); - man.destroy(done); - }); - it("Checking creation of two managers", (done) => { - const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - const man2 = new Manager(false); - - waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { - waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); - }); - }); - it("Checking creation 100 managers", (done) => { - const mans = []; - const amount = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let destroyed = 0; - let waitObj = {done: false}; - - Config.worldWidth = 10; - Config.worldHeight = 10; - for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} - for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} - - if (waitObj.done) { - Config.worldWidth = width; - Config.worldHeight = height; - done(); - return; - } - wait(waitObj, () => { - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }, 31000); - }); - - it("Checking running manager", (done) => { - const man = new Manager(false); - man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); - }); - it("Checking if manager runs main loop", (done) => { - const man = new Manager(false); - let count = 0; - man.run(() => man.on(EVENTS.ITERATION, () => { - ++count === 100 && man.destroy(done); - })); - }); - - it("Checking RUN event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); - }); - it("Checking STOP event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - it("Checking DESTROY event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); - }); - }); - }); - it("Checking ITERATION event", (done) => { - const man = new Manager(false); - let ok = false; - - man.on(EVENTS.ITERATION, () => ok = true); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - expect(ok).toBe(true); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - - it("Checking isDistributed() method", (done) => { - const man = new Manager(false); - - expect(man.isDistributed()).toBe(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - expect(man.isDistributed()).toBe(false); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - expect(man.isDistributed()).toBe(false); - man.destroy(done); - }); - }); - }); - it("Checking 'codeRuns' property", (done) => { - const man = new Manager(false); - let ok = false; - - man.on(EVENTS.ITERATION, () => ok = true); - expect(man.codeRuns).toBe(0); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // codeRuns should be 0, because there is no code lines - expect(man.codeRuns).toBe(0); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - - it("Checking running of manager with a server", (done) => { - const server = new Server(); - const man = new Manager(false); - - expect(man.clientId).toBe(null); - server.run(); - man.run(() => { - expect(man.active).toBe(true); - expect(man.clientId !== null).toBe(true); - man.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); - }); - }); - }); - - it("Checking one organism creation in a manager", (done) => { - const man = new Manager(false); - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const clone = OConfig.orgClonePeriod; - let iterated = false; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgClonePeriod = 0; - expect(man.organisms.size).toBe(0); - man.on(EVENTS.ITERATION, () => { - if (iterated) {return} - expect(man.organisms.size).toBe(1); - man.stop(() => { - man.destroy(() => { - OConfig.orgClonePeriod = clone; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - done(); - }); - }); - iterated = true; - }); - man.run(); - }); - it("Checking two managers with a server", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const server = new Server(); - const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - const man2 = new Manager(false); - let iterated1 = false; - let iterated2 = false; - let blocked = false; - const destroy = () => { - blocked = true; - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - expect(man1.clientId).toBe(null); - expect(man2.clientId).toBe(null); - expect(man1.organisms.size).toBe(0); - expect(man2.organisms.size).toBe(0); - server.run(); - - man1.on(EVENTS.ITERATION, () => { - if (blocked) {return} - expect(man1.organisms.size).toBe(1); - if (iterated1 && iterated2) {destroy(); return} - iterated1 = true; - }); - man2.on(EVENTS.ITERATION, () => { - if (blocked) {return} - expect(man2.organisms.size).toBe(1); - if (iterated2 && iterated1) {destroy(); return} - iterated2 = true; - }); - - man1.run(() => { - expect(man1.active).toBe(true); - expect(man1.clientId !== null).toBe(true); - man2.run(() => { - expect(man2.active).toBe(true); - expect(man2.clientId !== null).toBe(true); - }); - }); - }); - - it("Checking moving of organism from one Manager to another", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const height = Config.worldHeight; - const energy = OConfig.orgStartEnergy; - const server = new Server(); - Config.worldHeight = 400; - const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - const man2 = new Manager(false); - let iterated1 = 0; - let iterated2 = 0; - let freePos = World.prototype.getFreePos; - let org1 = null; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldHeight = height; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgStartEnergy = 10000; - World.prototype.getFreePos = () => {return {x: 1, y: 399}}; - - man1.on(EVENTS.ITERATION, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - } else if (man2.organisms.size === 2) { - destroy(); - } - if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - iterated1++; - }); - man2.on(EVENTS.ITERATION, () => iterated2++); - - server.run(); - man1.run(man2.run); - }); - /** - * The meaning of this test is in checking if one organism from up manager - * will go into the down manager, but there will be another organism. First - * organism should die in this case. - */ - it("Checking moving of organism from one Manager to another 2", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const height = Config.worldHeight; - const energy = OConfig.orgStartEnergy; - const server = new Server(); - Config.worldHeight = 400; - const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - const man2 = new Manager(false); - let iterated1 = 0; - let iterated2 = 0; - let freePos = World.prototype.getFreePos; - let org1 = null; - let org2 = null; - let inc = 0; - let doneInc = 0; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldHeight = height; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgStartEnergy = 10000; - World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; - - man1.on(EVENTS.ITERATION, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - man1.on(EVENTS.STEP_OUT, () => { - expect(doneInc < 3).toBe(true); - ++doneInc; - }); - man2.on(EVENTS.STEP_IN, () => { - ++doneInc; - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.y).toBe(0); - }); - } else if (org1 !== null && org2 !== null && doneInc === 2) { - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.y).toBe(0); - expect(man2.organisms.size).toBe(1); - expect(man2.organisms.first.val.y).toBe(0); - destroy(); - doneInc++; - } - if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - iterated1++; - }); - man2.on(EVENTS.ITERATION, () => { - !iterated2 && (org2 = man2.organisms.first.val); - iterated2++; - }); - - server.run(); - man1.run(man2.run); - }); - - it("Testing hundred managers and one server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const mans = []; - const CLIENTS = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let amount = 0; - let waitObj = {done: false}; - let man; - - Config.worldWidth = 100; - Config.worldHeight = 100; - SConfig.maxConnections = CLIENTS; - server.run(); - for (let i = 0; i < CLIENTS; i++) { - delete Config.organisms; - delete Config.status; - mans.push(man = new Manager(false)); - man.run(() => ++amount === CLIENTS && (waitObj.done = true)); - } - wait(waitObj, () => { - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); - for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }, 31000); - }); - it("Testing run/stop/run manager and one server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const CLIENTS = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let amount = 0; - let waitObj = {done: false}; - let count = 0; - let man1; - let man2; - let oldId; - - Config.worldWidth = 100; - Config.worldHeight = 100; - SConfig.maxConnections = CLIENTS; - man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - man2 = new Manager(false); - - server.run(); - man1.run(() => ++count === 2 && (waitObj.done = true)); - man2.run(() => ++count === 2 && (waitObj.done = true)); - wait(waitObj, () => { - man1.stop(() => { - expect(man1.clientId).toBe(null); - oldId = man1.clientId; - man1.run(() => { - expect(man1.clientId).not.toBe(null); - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - man1.destroy(); - man2.destroy(); - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }); - }); - }); - }); - - it("Tests many connections/disconnections of Manager to the server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const CLIENTS = 16; - const width = Config.worldWidth; - const height = Config.worldHeight; - let waitObj = {done: false}; - let amount = 0; - let count = 0; - let man1; - let man2; - const cb = () => { - man1.stop(() => { - expect(man1.clientId).toBe(null); - man1.run(() => { - expect(man1.clientId).not.toBe(null); - if (++amount < 10) { - cb(); - return; - } - man1.destroy(); - man2.destroy(); - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }); - }); - }; - - Config.worldWidth = 10; - Config.worldHeight = 10; - SConfig.maxConnections = CLIENTS; - man1 = new Manager(false); - delete Config.organisms; - delete Config.status; - man2 = new Manager(false); - - server.run(); - man1.run(() => ++count === 2 && (waitObj.done = true)); - man2.run(() => ++count === 2 && (waitObj.done = true)); - wait(waitObj, cb); - }); - - it('Tests organism moving from client of one server to client of other server', () => { + // it("Checking manager creation", (done) => { + // const man = new Manager(false); + // expect(man.canvas).toBe(null); + // man.destroy(done); + // }); + // it("Checking manager creation and it's properties", (done) => { + // const man = new Manager(false); + // expect(man.organisms.size).toBe(0); + // expect(Object.keys(man.positions).length).toBe(0); + // expect(man.codeRuns).toBe(0); + // expect(!!man.api.version).toBe(true); + // expect(man.api.visualize).toBe(undefined); + // expect(man.active).toBe(false); + // expect(man.clientId).toBe(null); + // expect(man.isDistributed()).toBe(false); + // expect(man.hasView).toBe(false); + // man.destroy(done); + // }); + // it("Checking creation of two managers", (done) => { + // const man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // const man2 = new Manager(false); + // + // waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { + // waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); + // }); + // }); + // it("Checking creation 100 managers", (done) => { + // const mans = []; + // const amount = 100; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // let destroyed = 0; + // let waitObj = {done: false}; + // + // Config.worldWidth = 10; + // Config.worldHeight = 10; + // for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} + // for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} + // + // if (waitObj.done) { + // Config.worldWidth = width; + // Config.worldHeight = height; + // done(); + // return; + // } + // wait(waitObj, () => { + // Config.worldWidth = width; + // Config.worldHeight = height; + // done(); + // }, 31000); + // }); + // + // it("Checking running manager", (done) => { + // const man = new Manager(false); + // man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); + // }); + // it("Checking if manager runs main loop", (done) => { + // const man = new Manager(false); + // let count = 0; + // man.run(() => man.on(EVENTS.ITERATION, () => { + // ++count === 100 && man.destroy(done); + // })); + // }); + // + // it("Checking RUN event", (done) => { + // const man = new Manager(false); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); + // }); + // it("Checking STOP event", (done) => { + // const man = new Manager(false); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + // }); + // }); + // it("Checking DESTROY event", (done) => { + // const man = new Manager(false); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // waitEvent(man, EVENTS.STOP, () => man.stop(), () => { + // waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); + // }); + // }); + // }); + // it("Checking ITERATION event", (done) => { + // const man = new Manager(false); + // let ok = false; + // + // man.on(EVENTS.ITERATION, () => ok = true); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // expect(ok).toBe(true); + // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + // }); + // }); + // + // it("Checking isDistributed() method", (done) => { + // const man = new Manager(false); + // + // expect(man.isDistributed()).toBe(false); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // expect(man.isDistributed()).toBe(false); + // waitEvent(man, EVENTS.STOP, () => man.stop(), () => { + // expect(man.isDistributed()).toBe(false); + // man.destroy(done); + // }); + // }); + // }); + // it("Checking 'codeRuns' property", (done) => { + // const man = new Manager(false); + // let ok = false; + // + // man.on(EVENTS.ITERATION, () => ok = true); + // expect(man.codeRuns).toBe(0); + // waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // // codeRuns should be 0, because there is no code lines + // expect(man.codeRuns).toBe(0); + // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + // }); + // }); + // + // it("Checking running of manager with a server", (done) => { + // const server = new Server(); + // const man = new Manager(false); + // + // expect(man.clientId).toBe(null); + // server.run(); + // man.run(() => { + // expect(man.active).toBe(true); + // expect(man.clientId !== null).toBe(true); + // man.destroy(() => { + // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); + // }); + // }); + // }); + // + // it("Checking one organism creation in a manager", (done) => { + // const man = new Manager(false); + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const clone = OConfig.orgClonePeriod; + // let iterated = false; + // + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgClonePeriod = 0; + // expect(man.organisms.size).toBe(0); + // man.on(EVENTS.ITERATION, () => { + // if (iterated) {return} + // expect(man.organisms.size).toBe(1); + // man.stop(() => { + // man.destroy(() => { + // OConfig.orgClonePeriod = clone; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // done(); + // }); + // }); + // iterated = true; + // }); + // man.run(); + // }); + // it("Checking two managers with a server", (done) => { + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const period1 = OConfig.orgEnergySpendPeriod; + // const clone = OConfig.orgClonePeriod; + // const server = new Server(); + // const man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // const man2 = new Manager(false); + // let iterated1 = false; + // let iterated2 = false; + // let blocked = false; + // const destroy = () => { + // blocked = true; + // man1.destroy(() => { + // man2.destroy(() => { + // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + // OConfig.orgClonePeriod = clone; + // OConfig.orgEnergySpendPeriod = period1; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // done(); + // }); + // }); + // }); + // }; + // + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgEnergySpendPeriod = 0; + // OConfig.orgClonePeriod = 0; + // expect(man1.clientId).toBe(null); + // expect(man2.clientId).toBe(null); + // expect(man1.organisms.size).toBe(0); + // expect(man2.organisms.size).toBe(0); + // server.run(); + // + // man1.on(EVENTS.ITERATION, () => { + // if (blocked) {return} + // expect(man1.organisms.size).toBe(1); + // if (iterated1 && iterated2) {destroy(); return} + // iterated1 = true; + // }); + // man2.on(EVENTS.ITERATION, () => { + // if (blocked) {return} + // expect(man2.organisms.size).toBe(1); + // if (iterated2 && iterated1) {destroy(); return} + // iterated2 = true; + // }); + // + // man1.run(() => { + // expect(man1.active).toBe(true); + // expect(man1.clientId !== null).toBe(true); + // man2.run(() => { + // expect(man2.active).toBe(true); + // expect(man2.clientId !== null).toBe(true); + // }); + // }); + // }); + + // it("Checking moving of organism from one Manager to another", (done) => { + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const period1 = OConfig.orgEnergySpendPeriod; + // const clone = OConfig.orgClonePeriod; + // const height = Config.worldHeight; + // const energy = OConfig.orgStartEnergy; + // const server = new Server(); + // Config.worldHeight = 400; + // const man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // const man2 = new Manager(false); + // let iterated1 = 0; + // let iterated2 = 0; + // let freePos = World.prototype.getFreePos; + // let org1 = null; + // const destroy = () => { + // man1.destroy(() => { + // man2.destroy(() => { + // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + // World.prototype.getFreePos = freePos; + // OConfig.orgStartEnergy = energy; + // OConfig.orgClonePeriod = clone; + // OConfig.orgEnergySpendPeriod = period1; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // Config.worldHeight = height; + // done(); + // }); + // }); + // }); + // }; + // + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgEnergySpendPeriod = 0; + // OConfig.orgClonePeriod = 0; + // OConfig.orgStartEnergy = 10000; + // World.prototype.getFreePos = () => {return {x: 1, y: 399}}; + // + // man1.on(EVENTS.ITERATION, () => { + // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + // org1 = man1.organisms.first.val; + // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + // } else if (man2.organisms.size === 2) { + // destroy(); + // } + // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + // iterated1++; + // }); + // man2.on(EVENTS.ITERATION, () => iterated2++); + // + // server.run(); + // man1.run(() => { + // man2.run(); + // }); + // }); + // /** + // * The meaning of this test is in checking if one organism from up manager + // * will go into the down manager, but there will be another organism. First + // * organism should die in this case. + // */ + // it("Checking moving of organism from one Manager to another 2", (done) => { + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const period1 = OConfig.orgEnergySpendPeriod; + // const clone = OConfig.orgClonePeriod; + // const height = Config.worldHeight; + // const energy = OConfig.orgStartEnergy; + // const server = new Server(); + // Config.worldHeight = 400; + // const man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // const man2 = new Manager(false); + // let iterated1 = 0; + // let iterated2 = 0; + // let freePos = World.prototype.getFreePos; + // let org1 = null; + // let org2 = null; + // let inc = 0; + // let doneInc = 0; + // const destroy = () => { + // man1.destroy(() => { + // man2.destroy(() => { + // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + // World.prototype.getFreePos = freePos; + // OConfig.orgStartEnergy = energy; + // OConfig.orgClonePeriod = clone; + // OConfig.orgEnergySpendPeriod = period1; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // Config.worldHeight = height; + // done(); + // }); + // }); + // }); + // }; + // + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgEnergySpendPeriod = 0; + // OConfig.orgClonePeriod = 0; + // OConfig.orgStartEnergy = 10000; + // World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; + // + // man1.on(EVENTS.ITERATION, () => { + // if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { + // org1 = man1.organisms.first.val; + // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + // man1.on(EVENTS.STEP_OUT, () => { + // expect(doneInc < 3).toBe(true); + // ++doneInc; + // }); + // man2.on(EVENTS.STEP_IN, () => { + // ++doneInc; + // expect(man1.organisms.size).toBe(1); + // expect(man1.organisms.first.val.y).toBe(0); + // }); + // } else if (org1 !== null && org2 !== null && doneInc === 2) { + // expect(man1.organisms.size).toBe(1); + // expect(man1.organisms.first.val.y).toBe(0); + // expect(man2.organisms.size).toBe(1); + // expect(man2.organisms.first.val.y).toBe(0); + // destroy(); + // doneInc++; + // } + // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + // iterated1++; + // }); + // man2.on(EVENTS.ITERATION, () => { + // !iterated2 && (org2 = man2.organisms.first.val); + // iterated2++; + // }); + // + // server.run(); + // man1.run(man2.run); + // }); + + // it("Testing hundred managers and one server", (done) => { + // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + // const maxCons = SConfig.maxConnections; + // const server = new Server(); + // const mans = []; + // const CLIENTS = 100; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // let amount = 0; + // let waitObj = {done: false}; + // let man; + // + // Config.worldWidth = 100; + // Config.worldHeight = 100; + // SConfig.maxConnections = CLIENTS; + // server.run(); + // for (let i = 0; i < CLIENTS; i++) { + // delete Config.organisms; + // delete Config.status; + // mans.push(man = new Manager(false)); + // man.run(() => ++amount === CLIENTS && (waitObj.done = true)); + // } + // wait(waitObj, () => { + // amount = 0; + // server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); + // for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} + // wait(waitObj, () => { + // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + // SConfig.maxConnections = maxCons; + // Config.worldWidth = width; + // Config.worldHeight = height; + // done(); + // }); + // }); + // }, 31000); + // }); + // it("Testing run/stop/run manager and one server", (done) => { + // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + // const maxCons = SConfig.maxConnections; + // const server = new Server(); + // const CLIENTS = 100; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // let amount = 0; + // let waitObj = {done: false}; + // let count = 0; + // let man1; + // let man2; + // let oldId; + // + // Config.worldWidth = 100; + // Config.worldHeight = 100; + // SConfig.maxConnections = CLIENTS; + // man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // man2 = new Manager(false); + // + // server.run(); + // man1.run(() => ++count === 2 && (waitObj.done = true)); + // man2.run(() => ++count === 2 && (waitObj.done = true)); + // wait(waitObj, () => { + // man1.stop(() => { + // expect(man1.clientId).toBe(null); + // oldId = man1.clientId; + // man1.run(() => { + // expect(man1.clientId).not.toBe(null); + // amount = 0; + // server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + // man1.destroy(); + // man2.destroy(); + // wait(waitObj, () => { + // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + // SConfig.maxConnections = maxCons; + // Config.worldWidth = width; + // Config.worldHeight = height; + // done(); + // }); + // }); + // }); + // }); + // }); + // }); + // + // it("Tests many connections/disconnections of Manager to the server", (done) => { + // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + // const maxCons = SConfig.maxConnections; + // const server = new Server(); + // const CLIENTS = 16; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // let waitObj = {done: false}; + // let amount = 0; + // let count = 0; + // let man1; + // let man2; + // const cb = () => { + // man1.stop(() => { + // expect(man1.clientId).toBe(null); + // man1.run(() => { + // expect(man1.clientId).not.toBe(null); + // if (++amount < 10) { + // cb(); + // return; + // } + // man1.destroy(); + // man2.destroy(); + // amount = 0; + // server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + // wait(waitObj, () => { + // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + // SConfig.maxConnections = maxCons; + // Config.worldWidth = width; + // Config.worldHeight = height; + // done(); + // }); + // }); + // }); + // }); + // }; + // + // Config.worldWidth = 10; + // Config.worldHeight = 10; + // SConfig.maxConnections = CLIENTS; + // man1 = new Manager(false); + // delete Config.organisms; + // delete Config.status; + // man2 = new Manager(false); + // + // server.run(); + // man1.run(() => ++count === 2 && (waitObj.done = true)); + // man2.run(() => ++count === 2 && (waitObj.done = true)); + // wait(waitObj, cb); + // }); + + it('Tests organism moving from client of one server to client of other server', (done) => { const amount = OConfig.orgStartAmount; const period = OConfig.orgRainMutationPeriod; const percent = OConfig.orgCloneMutationPercent; @@ -603,6 +608,11 @@ describe("client/src/manager/Manager", () => { const suport = SConfig.upPort; const maxConns = SConfig.maxConnections; const distrib = SConfig.modeDistributed; + const iters = OConfig.codeIterationsPerOnce; + const upHost = SConfig.upHost; + const rightHost = SConfig.rightHost; + const downHost = SConfig.downHost; + const leftHost = SConfig.leftHost; const freePos = World.prototype.getFreePos; let iterated1 = 0; let iterated2 = 0; @@ -628,12 +638,22 @@ describe("client/src/manager/Manager", () => { SConfig.maxConnections = maxConns; Config.worldCyclical = cycl; SConfig.modeDistributed = distrib; + OConfig.codeIterationsPerOnce = iters; + SConfig.upHost = upHost; + SConfig.rightHost = rightHost; + SConfig.downHost = downHost; + SConfig.leftHost = leftHost; done(); }); }); }); }; + SConfig.upHost = SERVER_HOST; + SConfig.rightHost = SERVER_HOST; + SConfig.downHost = SERVER_HOST; + SConfig.leftHost = SERVER_HOST; + OConfig.codeIterationsPerOnce = 1; SConfig.modeDistributed = true; SConfig.maxConnections = 1; SConfig.port = 3000; @@ -641,6 +661,7 @@ describe("client/src/manager/Manager", () => { const server1 = new Server(); // up server SConfig.port = 3001; SConfig.upPort = 3000; + SConfig.downPort = 1001; const server2 = new Server(); // down server Config.worldWidth = 10; Config.worldHeight = 10; @@ -672,8 +693,10 @@ describe("client/src/manager/Manager", () => { }); man2.on(EVENTS.ITERATION, () => iterated2++); - server1.run(); - server2.run(); - man1.run(man2.run); + waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { + waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { + man1.run(man2.run); + }); + }); }); }); \ No newline at end of file diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 0e04c0c..c498f05 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -161,8 +161,6 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json */ _moveToServer(clientId, x, y, dir, orgJson) { - const region = Connections.toRegion(clientId); - const sock = this.parent.aroundServers.getSocket(dir); sock && this.parent.request(sock, TYPES.REQ_MOVE_ORG_FROM_SERVER, clientId, x, y, dir, orgJson); } From 56fc8201685e80b42d221549166a4d8a731c0500 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 24 Dec 2017 10:26:48 +0200 Subject: [PATCH 062/291] done with complicated test of moving organism from client of one server to client of other server #83 --- client/src/manager/ManagerSpec.js | 1105 +++++++++++++++-------------- 1 file changed, 554 insertions(+), 551 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index c82ee35..e89fe73 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -49,28 +49,28 @@ describe("client/src/manager/Manager", () => { OConfig.orgStartAmount = 0; Config.worldEnergyCheckPeriod = 0; - // error = Console.error; - // warn = Console.warn; - // info = Console.info; - // Console.error = emptyFn; - // Console.warn = emptyFn; - // Console.info = emptyFn; - // - // serror = SConsole.error; - // swarn = SConsole.warn; - // sinfo = SConsole.info; - // SConsole.error = emptyFn; - // SConsole.warn = emptyFn; - // SConsole.info = emptyFn; + error = Console.error; + warn = Console.warn; + info = Console.info; + Console.error = emptyFn; + Console.warn = emptyFn; + Console.info = emptyFn; + + serror = SConsole.error; + swarn = SConsole.warn; + sinfo = SConsole.info; + SConsole.error = emptyFn; + SConsole.warn = emptyFn; + SConsole.info = emptyFn; }); afterAll(() => { - // SConsole.error = serror; - // SConsole.warn = swarn; - // SConsole.info = sinfo; - // - // Console.error = error; - // Console.warn = warn; - // Console.info = info; + SConsole.error = serror; + SConsole.warn = swarn; + SConsole.info = sinfo; + + Console.error = error; + Console.warn = warn; + Console.info = info; Config.modeNodeJs = OLD_MODE; Config.plugIncluded.push('ips/Ips'); jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; @@ -82,514 +82,515 @@ describe("client/src/manager/Manager", () => { Config.worldEnergyCheckPeriod = energyCheck; }); - // it("Checking manager creation", (done) => { - // const man = new Manager(false); - // expect(man.canvas).toBe(null); - // man.destroy(done); - // }); - // it("Checking manager creation and it's properties", (done) => { - // const man = new Manager(false); - // expect(man.organisms.size).toBe(0); - // expect(Object.keys(man.positions).length).toBe(0); - // expect(man.codeRuns).toBe(0); - // expect(!!man.api.version).toBe(true); - // expect(man.api.visualize).toBe(undefined); - // expect(man.active).toBe(false); - // expect(man.clientId).toBe(null); - // expect(man.isDistributed()).toBe(false); - // expect(man.hasView).toBe(false); - // man.destroy(done); - // }); - // it("Checking creation of two managers", (done) => { - // const man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // const man2 = new Manager(false); - // - // waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { - // waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); - // }); - // }); - // it("Checking creation 100 managers", (done) => { - // const mans = []; - // const amount = 100; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // let destroyed = 0; - // let waitObj = {done: false}; - // - // Config.worldWidth = 10; - // Config.worldHeight = 10; - // for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} - // for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} - // - // if (waitObj.done) { - // Config.worldWidth = width; - // Config.worldHeight = height; - // done(); - // return; - // } - // wait(waitObj, () => { - // Config.worldWidth = width; - // Config.worldHeight = height; - // done(); - // }, 31000); - // }); - // - // it("Checking running manager", (done) => { - // const man = new Manager(false); - // man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); - // }); - // it("Checking if manager runs main loop", (done) => { - // const man = new Manager(false); - // let count = 0; - // man.run(() => man.on(EVENTS.ITERATION, () => { - // ++count === 100 && man.destroy(done); - // })); - // }); - // - // it("Checking RUN event", (done) => { - // const man = new Manager(false); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); - // }); - // it("Checking STOP event", (done) => { - // const man = new Manager(false); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - // }); - // }); - // it("Checking DESTROY event", (done) => { - // const man = new Manager(false); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - // waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); - // }); - // }); - // }); - // it("Checking ITERATION event", (done) => { - // const man = new Manager(false); - // let ok = false; - // - // man.on(EVENTS.ITERATION, () => ok = true); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // expect(ok).toBe(true); - // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - // }); - // }); - // - // it("Checking isDistributed() method", (done) => { - // const man = new Manager(false); - // - // expect(man.isDistributed()).toBe(false); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // expect(man.isDistributed()).toBe(false); - // waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - // expect(man.isDistributed()).toBe(false); - // man.destroy(done); - // }); - // }); - // }); - // it("Checking 'codeRuns' property", (done) => { - // const man = new Manager(false); - // let ok = false; - // - // man.on(EVENTS.ITERATION, () => ok = true); - // expect(man.codeRuns).toBe(0); - // waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // // codeRuns should be 0, because there is no code lines - // expect(man.codeRuns).toBe(0); - // waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - // }); - // }); - // - // it("Checking running of manager with a server", (done) => { - // const server = new Server(); - // const man = new Manager(false); - // - // expect(man.clientId).toBe(null); - // server.run(); - // man.run(() => { - // expect(man.active).toBe(true); - // expect(man.clientId !== null).toBe(true); - // man.destroy(() => { - // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); - // }); - // }); - // }); - // - // it("Checking one organism creation in a manager", (done) => { - // const man = new Manager(false); - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const clone = OConfig.orgClonePeriod; - // let iterated = false; - // - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgClonePeriod = 0; - // expect(man.organisms.size).toBe(0); - // man.on(EVENTS.ITERATION, () => { - // if (iterated) {return} - // expect(man.organisms.size).toBe(1); - // man.stop(() => { - // man.destroy(() => { - // OConfig.orgClonePeriod = clone; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // done(); - // }); - // }); - // iterated = true; - // }); - // man.run(); - // }); - // it("Checking two managers with a server", (done) => { - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const period1 = OConfig.orgEnergySpendPeriod; - // const clone = OConfig.orgClonePeriod; - // const server = new Server(); - // const man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // const man2 = new Manager(false); - // let iterated1 = false; - // let iterated2 = false; - // let blocked = false; - // const destroy = () => { - // blocked = true; - // man1.destroy(() => { - // man2.destroy(() => { - // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - // OConfig.orgClonePeriod = clone; - // OConfig.orgEnergySpendPeriod = period1; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // done(); - // }); - // }); - // }); - // }; - // - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgEnergySpendPeriod = 0; - // OConfig.orgClonePeriod = 0; - // expect(man1.clientId).toBe(null); - // expect(man2.clientId).toBe(null); - // expect(man1.organisms.size).toBe(0); - // expect(man2.organisms.size).toBe(0); - // server.run(); - // - // man1.on(EVENTS.ITERATION, () => { - // if (blocked) {return} - // expect(man1.organisms.size).toBe(1); - // if (iterated1 && iterated2) {destroy(); return} - // iterated1 = true; - // }); - // man2.on(EVENTS.ITERATION, () => { - // if (blocked) {return} - // expect(man2.organisms.size).toBe(1); - // if (iterated2 && iterated1) {destroy(); return} - // iterated2 = true; - // }); - // - // man1.run(() => { - // expect(man1.active).toBe(true); - // expect(man1.clientId !== null).toBe(true); - // man2.run(() => { - // expect(man2.active).toBe(true); - // expect(man2.clientId !== null).toBe(true); - // }); - // }); - // }); - - // it("Checking moving of organism from one Manager to another", (done) => { - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const period1 = OConfig.orgEnergySpendPeriod; - // const clone = OConfig.orgClonePeriod; - // const height = Config.worldHeight; - // const energy = OConfig.orgStartEnergy; - // const server = new Server(); - // Config.worldHeight = 400; - // const man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // const man2 = new Manager(false); - // let iterated1 = 0; - // let iterated2 = 0; - // let freePos = World.prototype.getFreePos; - // let org1 = null; - // const destroy = () => { - // man1.destroy(() => { - // man2.destroy(() => { - // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - // World.prototype.getFreePos = freePos; - // OConfig.orgStartEnergy = energy; - // OConfig.orgClonePeriod = clone; - // OConfig.orgEnergySpendPeriod = period1; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // Config.worldHeight = height; - // done(); - // }); - // }); - // }); - // }; - // - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgEnergySpendPeriod = 0; - // OConfig.orgClonePeriod = 0; - // OConfig.orgStartEnergy = 10000; - // World.prototype.getFreePos = () => {return {x: 1, y: 399}}; - // - // man1.on(EVENTS.ITERATION, () => { - // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - // org1 = man1.organisms.first.val; - // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - // } else if (man2.organisms.size === 2) { - // destroy(); - // } - // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - // iterated1++; - // }); - // man2.on(EVENTS.ITERATION, () => iterated2++); - // - // server.run(); - // man1.run(() => { - // man2.run(); - // }); - // }); - // /** - // * The meaning of this test is in checking if one organism from up manager - // * will go into the down manager, but there will be another organism. First - // * organism should die in this case. - // */ - // it("Checking moving of organism from one Manager to another 2", (done) => { - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const period1 = OConfig.orgEnergySpendPeriod; - // const clone = OConfig.orgClonePeriod; - // const height = Config.worldHeight; - // const energy = OConfig.orgStartEnergy; - // const server = new Server(); - // Config.worldHeight = 400; - // const man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // const man2 = new Manager(false); - // let iterated1 = 0; - // let iterated2 = 0; - // let freePos = World.prototype.getFreePos; - // let org1 = null; - // let org2 = null; - // let inc = 0; - // let doneInc = 0; - // const destroy = () => { - // man1.destroy(() => { - // man2.destroy(() => { - // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - // World.prototype.getFreePos = freePos; - // OConfig.orgStartEnergy = energy; - // OConfig.orgClonePeriod = clone; - // OConfig.orgEnergySpendPeriod = period1; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // Config.worldHeight = height; - // done(); - // }); - // }); - // }); - // }; - // - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgEnergySpendPeriod = 0; - // OConfig.orgClonePeriod = 0; - // OConfig.orgStartEnergy = 10000; - // World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; - // - // man1.on(EVENTS.ITERATION, () => { - // if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { - // org1 = man1.organisms.first.val; - // org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - // man1.on(EVENTS.STEP_OUT, () => { - // expect(doneInc < 3).toBe(true); - // ++doneInc; - // }); - // man2.on(EVENTS.STEP_IN, () => { - // ++doneInc; - // expect(man1.organisms.size).toBe(1); - // expect(man1.organisms.first.val.y).toBe(0); - // }); - // } else if (org1 !== null && org2 !== null && doneInc === 2) { - // expect(man1.organisms.size).toBe(1); - // expect(man1.organisms.first.val.y).toBe(0); - // expect(man2.organisms.size).toBe(1); - // expect(man2.organisms.first.val.y).toBe(0); - // destroy(); - // doneInc++; - // } - // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - // iterated1++; - // }); - // man2.on(EVENTS.ITERATION, () => { - // !iterated2 && (org2 = man2.organisms.first.val); - // iterated2++; - // }); - // - // server.run(); - // man1.run(man2.run); - // }); - - // it("Testing hundred managers and one server", (done) => { - // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - // const maxCons = SConfig.maxConnections; - // const server = new Server(); - // const mans = []; - // const CLIENTS = 100; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // let amount = 0; - // let waitObj = {done: false}; - // let man; - // - // Config.worldWidth = 100; - // Config.worldHeight = 100; - // SConfig.maxConnections = CLIENTS; - // server.run(); - // for (let i = 0; i < CLIENTS; i++) { - // delete Config.organisms; - // delete Config.status; - // mans.push(man = new Manager(false)); - // man.run(() => ++amount === CLIENTS && (waitObj.done = true)); - // } - // wait(waitObj, () => { - // amount = 0; - // server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); - // for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} - // wait(waitObj, () => { - // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - // SConfig.maxConnections = maxCons; - // Config.worldWidth = width; - // Config.worldHeight = height; - // done(); - // }); - // }); - // }, 31000); - // }); - // it("Testing run/stop/run manager and one server", (done) => { - // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - // const maxCons = SConfig.maxConnections; - // const server = new Server(); - // const CLIENTS = 100; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // let amount = 0; - // let waitObj = {done: false}; - // let count = 0; - // let man1; - // let man2; - // let oldId; - // - // Config.worldWidth = 100; - // Config.worldHeight = 100; - // SConfig.maxConnections = CLIENTS; - // man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // man2 = new Manager(false); - // - // server.run(); - // man1.run(() => ++count === 2 && (waitObj.done = true)); - // man2.run(() => ++count === 2 && (waitObj.done = true)); - // wait(waitObj, () => { - // man1.stop(() => { - // expect(man1.clientId).toBe(null); - // oldId = man1.clientId; - // man1.run(() => { - // expect(man1.clientId).not.toBe(null); - // amount = 0; - // server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - // man1.destroy(); - // man2.destroy(); - // wait(waitObj, () => { - // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - // SConfig.maxConnections = maxCons; - // Config.worldWidth = width; - // Config.worldHeight = height; - // done(); - // }); - // }); - // }); - // }); - // }); - // }); - // - // it("Tests many connections/disconnections of Manager to the server", (done) => { - // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - // const maxCons = SConfig.maxConnections; - // const server = new Server(); - // const CLIENTS = 16; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // let waitObj = {done: false}; - // let amount = 0; - // let count = 0; - // let man1; - // let man2; - // const cb = () => { - // man1.stop(() => { - // expect(man1.clientId).toBe(null); - // man1.run(() => { - // expect(man1.clientId).not.toBe(null); - // if (++amount < 10) { - // cb(); - // return; - // } - // man1.destroy(); - // man2.destroy(); - // amount = 0; - // server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - // wait(waitObj, () => { - // waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - // SConfig.maxConnections = maxCons; - // Config.worldWidth = width; - // Config.worldHeight = height; - // done(); - // }); - // }); - // }); - // }); - // }; - // - // Config.worldWidth = 10; - // Config.worldHeight = 10; - // SConfig.maxConnections = CLIENTS; - // man1 = new Manager(false); - // delete Config.organisms; - // delete Config.status; - // man2 = new Manager(false); - // - // server.run(); - // man1.run(() => ++count === 2 && (waitObj.done = true)); - // man2.run(() => ++count === 2 && (waitObj.done = true)); - // wait(waitObj, cb); - // }); + it("Checking manager creation", (done) => { + const man = new Manager(false); + expect(man.canvas).toBe(null); + man.destroy(done); + }); + it("Checking manager creation and it's properties", (done) => { + const man = new Manager(false); + expect(man.organisms.size).toBe(0); + expect(Object.keys(man.positions).length).toBe(0); + expect(man.codeRuns).toBe(0); + expect(!!man.api.version).toBe(true); + expect(man.api.visualize).toBe(undefined); + expect(man.active).toBe(false); + expect(man.clientId).toBe(null); + expect(man.isDistributed()).toBe(false); + expect(man.hasView).toBe(false); + man.destroy(done); + }); + it("Checking creation of two managers", (done) => { + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man2 = new Manager(false); + + waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { + waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); + }); + }); + it("Checking creation 100 managers", (done) => { + const mans = []; + const amount = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let destroyed = 0; + let waitObj = {done: false}; + + Config.worldWidth = 10; + Config.worldHeight = 10; + for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} + for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} + + if (waitObj.done) { + Config.worldWidth = width; + Config.worldHeight = height; + done(); + return; + } + wait(waitObj, () => { + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }, 31000); + }); + + it("Checking running manager", (done) => { + const man = new Manager(false); + man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); + }); + it("Checking if manager runs main loop", (done) => { + const man = new Manager(false); + let count = 0; + man.run(() => man.on(EVENTS.ITERATION, () => { + ++count === 100 && man.destroy(done); + })); + }); + + it("Checking RUN event", (done) => { + const man = new Manager(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); + }); + it("Checking STOP event", (done) => { + const man = new Manager(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + it("Checking DESTROY event", (done) => { + const man = new Manager(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + waitEvent(man, EVENTS.STOP, () => man.stop(), () => { + waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); + }); + }); + }); + it("Checking ITERATION event", (done) => { + const man = new Manager(false); + let ok = false; + + man.on(EVENTS.ITERATION, () => ok = true); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + expect(ok).toBe(true); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + + it("Checking isDistributed() method", (done) => { + const man = new Manager(false); + + expect(man.isDistributed()).toBe(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + expect(man.isDistributed()).toBe(false); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => { + expect(man.isDistributed()).toBe(false); + man.destroy(done); + }); + }); + }); + it("Checking 'codeRuns' property", (done) => { + const man = new Manager(false); + let ok = false; + + man.on(EVENTS.ITERATION, () => ok = true); + expect(man.codeRuns).toBe(0); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // codeRuns should be 0, because there is no code lines + expect(man.codeRuns).toBe(0); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + + it("Checking running of manager with a server", (done) => { + const server = new Server(); + const man = new Manager(false); + + expect(man.clientId).toBe(null); + server.run(); + man.run(() => { + expect(man.active).toBe(true); + expect(man.clientId !== null).toBe(true); + man.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); + }); + }); + }); + + it("Checking one organism creation in a manager", (done) => { + const man = new Manager(false); + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const clone = OConfig.orgClonePeriod; + let iterated = false; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgClonePeriod = 0; + expect(man.organisms.size).toBe(0); + man.on(EVENTS.ITERATION, () => { + if (iterated) {return} + expect(man.organisms.size).toBe(1); + man.stop(() => { + man.destroy(() => { + OConfig.orgClonePeriod = clone; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + done(); + }); + }); + iterated = true; + }); + man.run(); + }); + it("Checking two managers with a server", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const clone = OConfig.orgClonePeriod; + const server = new Server(); + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man2 = new Manager(false); + let iterated1 = false; + let iterated2 = false; + let blocked = false; + const destroy = () => { + blocked = true; + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + OConfig.orgClonePeriod = clone; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgClonePeriod = 0; + expect(man1.clientId).toBe(null); + expect(man2.clientId).toBe(null); + expect(man1.organisms.size).toBe(0); + expect(man2.organisms.size).toBe(0); + server.run(); + + man1.on(EVENTS.ITERATION, () => { + if (blocked) {return} + expect(man1.organisms.size).toBe(1); + if (iterated1 && iterated2) {destroy(); return} + iterated1 = true; + }); + man2.on(EVENTS.ITERATION, () => { + if (blocked) {return} + expect(man2.organisms.size).toBe(1); + if (iterated2 && iterated1) {destroy(); return} + iterated2 = true; + }); + + man1.run(() => { + expect(man1.active).toBe(true); + expect(man1.clientId !== null).toBe(true); + man2.run(() => { + expect(man2.active).toBe(true); + expect(man2.clientId !== null).toBe(true); + }); + }); + }); + + it("Checking moving of organism from one Manager to another", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const clone = OConfig.orgClonePeriod; + const height = Config.worldHeight; + const energy = OConfig.orgStartEnergy; + const server = new Server(); + Config.worldHeight = 400; + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man2 = new Manager(false); + let iterated1 = 0; + let iterated2 = 0; + let freePos = World.prototype.getFreePos; + let org1 = null; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgClonePeriod = clone; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldHeight = height; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgClonePeriod = 0; + OConfig.orgStartEnergy = 10000; + World.prototype.getFreePos = () => {return {x: 1, y: 399}}; + + man1.on(EVENTS.ITERATION, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + } else if (man2.organisms.size === 2) { + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + iterated1++; + }); + man2.on(EVENTS.ITERATION, () => iterated2++); + + server.run(); + man1.run(() => { + man2.run(); + }); + }); + /** + * The meaning of this test is in checking if one organism from up manager + * will go into the down manager, but there will be another organism. First + * organism should die in this case. + */ + it("Checking moving of organism from one Manager to another 2", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const clone = OConfig.orgClonePeriod; + const height = Config.worldHeight; + const energy = OConfig.orgStartEnergy; + const server = new Server(); + Config.worldHeight = 400; + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man2 = new Manager(false); + let iterated1 = 0; + let iterated2 = 0; + let freePos = World.prototype.getFreePos; + let org1 = null; + let org2 = null; + let inc = 0; + let doneInc = 0; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgClonePeriod = clone; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldHeight = height; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgClonePeriod = 0; + OConfig.orgStartEnergy = 10000; + World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; + + man1.on(EVENTS.ITERATION, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + man1.on(EVENTS.STEP_OUT, () => { + expect(doneInc < 3).toBe(true); + ++doneInc; + }); + man2.on(EVENTS.STEP_IN, () => { + ++doneInc; + expect(man1.organisms.size).toBe(1); + expect(man1.organisms.first.val.y).toBe(0); + }); + } else if (org1 !== null && org2 !== null && doneInc === 2) { + expect(man1.organisms.size).toBe(1); + expect(man1.organisms.first.val.y).toBe(0); + expect(man2.organisms.size).toBe(1); + expect(man2.organisms.first.val.y).toBe(0); + destroy(); + doneInc++; + } + if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + iterated1++; + }); + man2.on(EVENTS.ITERATION, () => { + !iterated2 && (org2 = man2.organisms.first.val); + iterated2++; + }); + + server.run(); + man1.run(man2.run); + }); + + it("Testing hundred managers and one server", (done) => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + const maxCons = SConfig.maxConnections; + const server = new Server(); + const mans = []; + const CLIENTS = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let amount = 0; + let waitObj = {done: false}; + let man; + + Config.worldWidth = 100; + Config.worldHeight = 100; + SConfig.maxConnections = CLIENTS; + server.run(); + for (let i = 0; i < CLIENTS; i++) { + delete Config.organisms; + delete Config.status; + mans.push(man = new Manager(false)); + man.run(() => ++amount === CLIENTS && (waitObj.done = true)); + } + wait(waitObj, () => { + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); + for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); + }); + }, 31000); + }); + it("Testing run/stop/run manager and one server", (done) => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + const maxCons = SConfig.maxConnections; + const server = new Server(); + const CLIENTS = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let amount = 0; + let waitObj = {done: false}; + let count = 0; + let man1; + let man2; + let oldId; + + Config.worldWidth = 100; + Config.worldHeight = 100; + SConfig.maxConnections = CLIENTS; + man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + man2 = new Manager(false); + + server.run(); + man1.run(() => ++count === 2 && (waitObj.done = true)); + man2.run(() => ++count === 2 && (waitObj.done = true)); + wait(waitObj, () => { + man1.stop(() => { + expect(man1.clientId).toBe(null); + oldId = man1.clientId; + man1.run(() => { + expect(man1.clientId).not.toBe(null); + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + man1.destroy(); + man2.destroy(); + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); + }); + }); + }); + }); + }); + + it("Tests many connections/disconnections of Manager to the server", (done) => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; + const maxCons = SConfig.maxConnections; + const server = new Server(); + const CLIENTS = 16; + const width = Config.worldWidth; + const height = Config.worldHeight; + let waitObj = {done: false}; + let amount = 0; + let count = 0; + let man1; + let man2; + const cb = () => { + man1.stop(() => { + expect(man1.clientId).toBe(null); + man1.run(() => { + expect(man1.clientId).not.toBe(null); + if (++amount < 10) { + cb(); + return; + } + man1.destroy(); + man2.destroy(); + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); + }); + }); + }); + }; + + Config.worldWidth = 10; + Config.worldHeight = 10; + SConfig.maxConnections = CLIENTS; + man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + man2 = new Manager(false); + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + man1.run(() => ++count === 2 && (waitObj.done = true)); + man2.run(() => ++count === 2 && (waitObj.done = true)); + wait(waitObj, cb); + }); + }); it('Tests organism moving from client of one server to client of other server', (done) => { const amount = OConfig.orgStartAmount; @@ -621,29 +622,31 @@ describe("client/src/manager/Manager", () => { man1.destroy(() => { man2.destroy(() => { waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldWidth = width; - Config.worldHeight = height; - SConfig.port = sport; - SConfig.downPort = sdport; - SConfig.upPort = suport; - Config.serverPort = cport; - Config.serverHost = chost; - SConfig.maxConnections = maxConns; - Config.worldCyclical = cycl; - SConfig.modeDistributed = distrib; - OConfig.codeIterationsPerOnce = iters; - SConfig.upHost = upHost; - SConfig.rightHost = rightHost; - SConfig.downHost = downHost; - SConfig.leftHost = leftHost; - done(); + waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgClonePeriod = clone; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldWidth = width; + Config.worldHeight = height; + SConfig.port = sport; + SConfig.downPort = sdport; + SConfig.upPort = suport; + Config.serverPort = cport; + Config.serverHost = chost; + SConfig.maxConnections = maxConns; + Config.worldCyclical = cycl; + SConfig.modeDistributed = distrib; + OConfig.codeIterationsPerOnce = iters; + SConfig.upHost = upHost; + SConfig.rightHost = rightHost; + SConfig.downHost = downHost; + SConfig.leftHost = leftHost; + done(); + }); }); }); }); From 87d1ef94f4faee73faa0ca7b316dcc368f7056f2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 24 Dec 2017 11:38:48 +0200 Subject: [PATCH 063/291] fixed tests #83 --- client/src/manager/ManagerSpec.js | 100 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index e89fe73..6f4655e 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -285,7 +285,6 @@ describe("client/src/manager/Manager", () => { expect(man2.clientId).toBe(null); expect(man1.organisms.size).toBe(0); expect(man2.organisms.size).toBe(0); - server.run(); man1.on(EVENTS.ITERATION, () => { if (blocked) {return} @@ -300,12 +299,14 @@ describe("client/src/manager/Manager", () => { iterated2 = true; }); - man1.run(() => { - expect(man1.active).toBe(true); - expect(man1.clientId !== null).toBe(true); - man2.run(() => { - expect(man2.active).toBe(true); - expect(man2.clientId !== null).toBe(true); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + man1.run(() => { + expect(man1.active).toBe(true); + expect(man1.clientId !== null).toBe(true); + man2.run(() => { + expect(man2.active).toBe(true); + expect(man2.clientId !== null).toBe(true); + }); }); }); }); @@ -366,10 +367,7 @@ describe("client/src/manager/Manager", () => { }); man2.on(EVENTS.ITERATION, () => iterated2++); - server.run(); - man1.run(() => { - man2.run(); - }); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); }); /** * The meaning of this test is in checking if one organism from up manager @@ -452,8 +450,7 @@ describe("client/src/manager/Manager", () => { iterated2++; }); - server.run(); - man1.run(man2.run); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); }); it("Testing hundred managers and one server", (done) => { @@ -471,26 +468,28 @@ describe("client/src/manager/Manager", () => { Config.worldWidth = 100; Config.worldHeight = 100; SConfig.maxConnections = CLIENTS; - server.run(); - for (let i = 0; i < CLIENTS; i++) { - delete Config.organisms; - delete Config.status; - mans.push(man = new Manager(false)); - man.run(() => ++amount === CLIENTS && (waitObj.done = true)); - } - wait(waitObj, () => { - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); - for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + for (let i = 0; i < CLIENTS; i++) { + delete Config.organisms; + delete Config.status; + mans.push(man = new Manager(false)); + man.run(() => ++amount === CLIENTS && (waitObj.done = true)); + } wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); + for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); }); - }); - }, 31000); + }, 31000); + }); }); it("Testing run/stop/run manager and one server", (done) => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; @@ -514,25 +513,26 @@ describe("client/src/manager/Manager", () => { delete Config.status; man2 = new Manager(false); - server.run(); - man1.run(() => ++count === 2 && (waitObj.done = true)); - man2.run(() => ++count === 2 && (waitObj.done = true)); - wait(waitObj, () => { - man1.stop(() => { - expect(man1.clientId).toBe(null); - oldId = man1.clientId; - man1.run(() => { - expect(man1.clientId).not.toBe(null); - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - man1.destroy(); - man2.destroy(); - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + man1.run(() => ++count === 2 && (waitObj.done = true)); + man2.run(() => ++count === 2 && (waitObj.done = true)); + wait(waitObj, () => { + man1.stop(() => { + expect(man1.clientId).toBe(null); + oldId = man1.clientId; + man1.run(() => { + expect(man1.clientId).not.toBe(null); + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + man1.destroy(); + man2.destroy(); + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); }); }); }); From 3c47c4bc5753307446fba7e5a6b309ac5144f25a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 24 Dec 2017 13:02:02 +0200 Subject: [PATCH 064/291] small refactoring of Organisms class --- client/src/manager/plugins/organisms/Organisms.js | 3 +-- client/src/manager/plugins/organisms/garmin/Organisms.js | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index ee36980..1e92b63 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -203,8 +203,7 @@ class Organisms extends Configurable { } reset() { - this._orgId = 0; - this._maxEnergy = 0; + this._orgId = 0; } move(x1, y1, x2, y2, org) { diff --git a/client/src/manager/plugins/organisms/garmin/Organisms.js b/client/src/manager/plugins/organisms/garmin/Organisms.js index cd09ad6..0624e43 100644 --- a/client/src/manager/plugins/organisms/garmin/Organisms.js +++ b/client/src/manager/plugins/organisms/garmin/Organisms.js @@ -10,7 +10,6 @@ * * @author flatline */ -const Config = require('./../../../../share/Config').Config; const Organism = require('./Organism'); const Console = require('./../../../../share/Console'); const EVENTS = require('./../../../../share/Events').EVENTS; @@ -21,6 +20,7 @@ class Organisms extends BaseOrganisms { constructor(manager) { super(manager); this._maxChanges = 0; + this._maxEnergy = 0; } /** @@ -54,6 +54,7 @@ class Organisms extends BaseOrganisms { reset() { super.reset(); this._maxChanges = 0; + this._maxEnergy = 0; } /** From 19cead4c9a20281dfcabf975474deccdf1023647 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 24 Dec 2017 13:54:15 +0200 Subject: [PATCH 065/291] added check in complex multi server test #83 --- client/src/manager/ManagerSpec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 6f4655e..0a4c8ca 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -686,6 +686,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() } else if (man2.organisms.size === 2) { From b66c7d967bed0409e4d57cd01566ceb02b1f8915 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 25 Dec 2017 16:48:48 +0200 Subject: [PATCH 066/291] added basic logic of returning back organisms from destination client, if there is no free space there #98 removed unused @private annotations --- .../src/manager/plugins/client/plugins/Api.js | 14 ++-- .../src/manager/plugins/organisms/Mutator.js | 1 - .../src/manager/plugins/organisms/Organism.js | 2 - .../manager/plugins/organisms/Organisms.js | 2 - .../plugins/organisms/dos/Code2String.js | 1 - .../plugins/organisms/dos/Operators.js | 1 - .../plugins/organisms/dos/Organisms.js | 9 +-- .../plugins/organisms/garmin/Organism.js | 1 - client/src/vm/VM.js | 1 - common/src/Configurable.js | 1 - common/src/Directions.js | 7 +- common/src/Helper.js | 13 ++++ common/src/net/Api.js | 1 - common/src/net/Requests.js | 18 ++--- common/src/plugins/Request.js | 1 - server/src/server/AroundServers.js | 6 +- server/src/server/plugins/Api.js | 71 ++++++++++++++----- 17 files changed, 97 insertions(+), 53 deletions(-) diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 7c043e9..7d9f88d 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -12,7 +12,8 @@ class Api extends BaseApi { constructor(client) { super(client); - this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this, false); + this.api[TYPES.REQ_MOVE_ORG_BACK] = this._stepIn.bind(this, true); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setActive.bind(this); } @@ -23,6 +24,7 @@ class Api extends BaseApi { /** * Is called if organism is move in from other Manager (world) + * @param {Boolean} back true, if organism is sent back * @param {String} reqId Unique request id * @param {String} clientId Unique client id within current server * @param {Number} x Current org X position @@ -31,8 +33,10 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _stepIn(reqId, clientId, x, y, dir, orgJson) { - this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson); + _stepIn(back, reqId, clientId, x, y, dir, orgJson) { + const ret = {ret: true}; + this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson, ret); + !back && this.parent.response(this.sock, ret.ret ? TYPES.RES_MOVE_OK : TYPES.RES_MOVE_ERR, reqId, clientId); } /** @@ -47,10 +51,6 @@ class Api extends BaseApi { _setActive(reqId, dir, active) { this.parent.manager.activeAround[dir] = active; } - - _request(type, ...params) { - return this.parent.request(this.parent.socket, type, this.parent.manager.clientId, ...params); - } } module.exports = Api; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 543c7e2..4483164 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -40,7 +40,6 @@ class Mutator { /** * Operator type or one variable may mutate * @param {Organism} org - * @private */ static _onSmallChange(org) { const rand = Helper.rand; diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 47e80d5..86e335b 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -215,7 +215,6 @@ class Organism extends Observer { /** * Checks if organism need to be killed/destroyed, because of age or zero energy * @return {Boolean} false means that organism was destroyed. - * @private */ _updateDestroy() { const alivePeriod = OConfig.orgAlivePeriod; @@ -230,7 +229,6 @@ class Organism extends Observer { * This is how our system grabs an energy= require(organism if it's age is * divided into OConfig.orgEnergySpendPeriod. * @return {Boolean} false means that organism was destroyed. - * @private */ _updateEnergy() { if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 1e92b63..d500a37 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -112,7 +112,6 @@ class Organisms extends Configurable { * iteration of main loop. The counter is an analog of time. * @param {Number} counter Value of main loop counter. * @param {Number} stamp Time stamp of current iteration - * @private */ onIteration(counter, stamp) { let item = this.organisms.first; @@ -145,7 +144,6 @@ class Organisms extends Configurable { * Cloning parents are chosen according to tournament principle * @param {Number} counter Current counter * @returns {boolean} - * @private */ updateClone(counter) { const orgs = this.organisms; diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index b8c109d..ccf43ce 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -256,7 +256,6 @@ class Code2String { * @param {Number} lines Amount of lines * @param {Number} offs Local offset of closing bracket we want to set * @returns {Number} - * @private */ _getOffs(line, lines, offs) { let offset = line + offs < lines ? line + offs + 1 : lines; diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 0d829dd..8febd12 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -268,7 +268,6 @@ class OperatorsDos extends Operators { * @param {Number} lines Amount of lines * @param {Number} offs Local offset of closing bracket we want to set * @returns {Number} - * @private */ _getOffs(line, lines, offs) { let offset = line + offs < lines ? line + offs + 1 : lines; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 8127c56..9dfd06f 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -202,14 +202,15 @@ class Organisms extends BaseOrganisms { /** * Is called if organism step in from the server or other client (Manager/World). * If step in position is not free or maximum organisms are in the world, then - * organism die at the moment. + * organism die at the moment. We have to set true to ret.ret, if in this world + * there is a free place for the organism. And false otherwise. * @param {Number} x Current org X position * @param {Number} y Current org Y position * @param {String} orgJson Organism's serialized json - * @private + * @param {Object} ret Return object */ - _onStepIn(x, y, orgJson) { - if (this.manager.world.isFree(x, y) && this.organisms.size < OConfig.orgMaxOrgs && this.createOrg({x, y})) { + _onStepIn(x, y, orgJson, ret) { + if (ret.ret = this.manager.world.isFree(x, y) && this.organisms.size < OConfig.orgMaxOrgs && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); org.grabEnergy(OConfig.orgStepEnergySpendPercent); diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index 37fdc35..c0a0dd8 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -48,7 +48,6 @@ class OrganismGarmin extends Organism { /** * Is called when some modifications in code appeared and we have * to re-execute it again - * @private */ _onResetCode() { this._needRun = true; diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index f46f808..b81db7e 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -251,7 +251,6 @@ class VM extends Observer { * Generates default variables vm. It should be in ES5 version, because * speed is important. Amount of vars depends on OConfig.codeBitsPerVar config. * @returns {Array} vars vm - * @private */ _getVars() { if (this._vars && this._vars.length > 0) {return this._vars} diff --git a/common/src/Configurable.js b/common/src/Configurable.js index 24aac64..dd7665c 100644 --- a/common/src/Configurable.js +++ b/common/src/Configurable.js @@ -78,7 +78,6 @@ class Configurable { * using api like this: man.api..show(). 'description' will be shown * if user types like this: man.api..show.desc. * @param {Object} apiCfg Object of name for key and String or Array for value - * @private */ _updateApi(apiCfg) { const api = this._parent.api; diff --git a/common/src/Directions.js b/common/src/Directions.js index d175171..07604e9 100644 --- a/common/src/Directions.js +++ b/common/src/Directions.js @@ -18,5 +18,10 @@ const NAMES = { 3: 'Left', 4: 'No' }; +/** + * {Array} Array of flipped directions. Is used for connecting with nearest + * servers: left -> right, up -> down, right -> left, down -> up + */ +const FLIP_DIR = [DIR.DOWN, DIR.LEFT, DIR.UP, DIR.RIGHT]; -module.exports = {DIR, NAMES}; \ No newline at end of file +module.exports = {DIR, FLIP_DIR, NAMES}; \ No newline at end of file diff --git a/common/src/Helper.js b/common/src/Helper.js index 2a0686c..62850e2 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -133,6 +133,19 @@ class Helper { return [x, y, dir]; } + /** + * Flips X or Y to the opposite coordinates. e.g: + * width=10, height=10, x=0, y=1 -> x=9, y=1 + * width=10, height=10, x=3, y=9 -> x=3, y=0 + * @param {Number} x X coordinate + * @param {Number} y Y coordinate + */ + static flip(x, y) { + const xMap = {0: Config.worldWidth - 1, [Config.worldWidth - 1]: 0}; + const yMap = {0: Config.worldHeight - 1, [Config.worldHeight - 1]: 0}; + return [xMap[x] ? xMap[x] : x, yMap[y] ? yMap[y] : y]; + } + /** * Analog of jQuery.isNumeric() * @param {*} n Value to check diff --git a/common/src/net/Api.js b/common/src/net/Api.js index c4aa861..6caf183 100644 --- a/common/src/net/Api.js +++ b/common/src/net/Api.js @@ -58,7 +58,6 @@ class Api { * answers. * @param {WebSocket} sock Communication socket * @param {Event} event Event with parameters obtained from the client - * @private */ _onMessage(sock, event) { const data = JSON.parse(event.data || event); diff --git a/common/src/net/Requests.js b/common/src/net/Requests.js index 433c8d6..fa2e01c 100644 --- a/common/src/net/Requests.js +++ b/common/src/net/Requests.js @@ -17,17 +17,19 @@ const TYPES = { // // Requests section // - REQ_MOVE_ORG : 0, // Organism moves from one world(manager) to another(sibling) - REQ_SET_NEAR_ACTIVE : 1, // Other (near) server wants to connect with current one - REQ_GET_ID : 2, // Client wants obtain it's unique id from server - REQ_MOVE_ORG_FROM_SERVER: 3, // Organism came from near server + REQ_MOVE_ORG : 0, // Organism moves from one world(manager) to another(sibling) + REQ_MOVE_ORG_BACK : 1, // Organism sends back to source client\server + REQ_SET_NEAR_ACTIVE : 2, // Other (near) server wants to connect with current one + REQ_GET_ID : 3, // Client wants obtain it's unique id from server + REQ_MOVE_ORG_FROM_SERVER : 4, // Organism came from near server // // Responses section // - RES_MOVE_ERR : 1000, - RES_INVALID_TYPE : 1001, - RES_GET_ID_OK : 1002, - RES_SET_NEAR_ACTIVE_OK : 1003 + RES_MOVE_ERR : 1000, + RES_MOVE_OK : 1001, + RES_INVALID_TYPE : 1002, + RES_GET_ID_OK : 1003, + RES_SET_NEAR_ACTIVE_OK : 1004 }; module.exports = {TYPES, MASKS}; \ No newline at end of file diff --git a/common/src/plugins/Request.js b/common/src/plugins/Request.js index b340cde..eb519cf 100644 --- a/common/src/plugins/Request.js +++ b/common/src/plugins/Request.js @@ -119,7 +119,6 @@ class Request { * [type, reqId|null, ...params]. * @param {WebSocket} sock Owner socket * @param {Event} event Event object with received data - * @private */ _onMessage(sock, event) { const data = JSON.parse(event.data || event); diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 9ae3e99..88f4494 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -16,17 +16,13 @@ * @author flatline */ const DIR = require('./../../../common/src/Directions').DIR; +const FLIP_DIR = require('./../../../common/src/Directions').FLIP_DIR; const NAMES = require('./../../../common/src/Directions').NAMES; const TYPES = require('./../../../common/src/net/Requests').TYPES; const AsyncParent = require('./../../../common/src/plugins/AsyncParent'); const Observer = require('./../../../common/src/Observer'); const Console = require('./../share/Console'); const Client = require('./Client'); -/** - * {Array} Array of flipped directions. Is used for connecting with nearest - * servers: left -> right, up -> down, right -> left, down -> up - */ -const FLIP_DIR = [DIR.DOWN, DIR.LEFT, DIR.UP, DIR.RIGHT]; /** * Events of this class */ diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index c498f05..02873d2 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -13,6 +13,7 @@ const Console = require('./../../share/Console'); const Connections = require('./../Connections'); const DIR = require('./../../../../common/src/Directions').DIR; +const FLIP_DIR = require('./../../../../common/src/Directions').FLIP_DIR; const NAMES = require('./../../../../common/src/Directions').NAMES; const BaseApi = require('./../../../../common/src/net/Api'); class Api extends BaseApi { @@ -20,10 +21,11 @@ class Api extends BaseApi { super(parent); const servers = parent.aroundServers; - this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrgFromClient.bind(this); - this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this); - this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); - this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); + this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrgFromClient.bind(this, false); + this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this); + this.api[TYPES.REQ_MOVE_ORG_BACK] = this._onMoveOrgFromClient.bind(this, true); + this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); + this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); this._onCloseCb = this._onClose.bind(this); this._onServerOpenCb = this._onServerOpen.bind(this); @@ -51,7 +53,7 @@ class Api extends BaseApi { /** * Moves organism from near server to current server * @param {Number} reqId Unique request id. Needed for response - * @param {String} clientId Unique client id of near server + * @param {String} clientId Unique source client id * @param {Number} x Current org X position * @param {Number} y Current org Y position * @param {Number} dir Moving direction @@ -61,21 +63,22 @@ class Api extends BaseApi { _onMoveOrgFromServer(reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const conns = this.parent.conns; - this._moveToClient(Connections.toId(conns.oppositeRegion(reg, dir)), x, y, dir, orgJson, false); + this._moveToClient(false, Connections.toId(conns.oppositeRegion(reg, dir)), x, y, dir, orgJson, false); } /** * Moves organism from one client to another or to nearest server if * it's connected to current one + * @param {Boolean} back true, if the organism is sent back * @param {Number} reqId Unique request id. Needed for response - * @param {String} clientId Unique client id + * @param {String} clientId Unique source client id * @param {Number} x Current org X position * @param {Number} y Current org Y position * @param {Number} dir Moving direction * @param {String} orgJson Organism's serialized json * @api */ - _onMoveOrgFromClient(reqId, clientId, x, y, dir, orgJson) { + _onMoveOrgFromClient(back, reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const side = this.parent.conns.side - 1; // @@ -84,7 +87,7 @@ class Api extends BaseApi { // if (dir === DIR.UP && reg[1] > 0 || dir === DIR.RIGHT && reg[0] < side || dir === DIR.DOWN && reg[1] < side || dir === DIR.LEFT && reg[0] > 0) { - this._moveToClient(clientId, x, y, dir, orgJson); + this._moveToClient(back, clientId, x, y, dir, orgJson); return; } // @@ -130,15 +133,19 @@ class Api extends BaseApi { } /** - * Moves organism's json to nearest client depending on dir parameter - * @param {String} clientId Unique client id + * Moves organism's json to nearest client depending on dir parameter. + * This method is called in both client->client or server->client directions. + * If destination client is not active or there is no free space for the + * organism, then it will be sent back to source client. + * @param {Boolean} back true, if organism is sent back + * @param {String} clientId Unique source client id * @param {Number} x Organism x coordinate * @param {Number} y Organism y coordinate * @param {Number} dir Moving direction * @param {String} orgJson Organism's serialized json * @param {Boolean} fromClient false if organism came from near server */ - _moveToClient(clientId, x, y, dir, orgJson, fromClient = true) { + _moveToClient(back, clientId, x, y, dir, orgJson, fromClient = true) { const region = Connections.toRegion(clientId); if (fromClient) { @@ -147,14 +154,27 @@ class Api extends BaseApi { else if (dir === DIR.DOWN) {region[1]++} else if (dir === DIR.LEFT) {region[0]--} } - + // + // If destination client active, then organism is moved there. + // Otherwise, we have to move it back to source client (possibly + // through near server) + // const con = this.parent.conns.getConnection(region); - con.active && this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, clientId, x, y, dir, orgJson); + if (con.active) { + this.parent.request(con.sock, TYPES.REQ_MOVE_ORG, clientId, x, y, dir, orgJson, (type) => { + // + // No free space for organism - send it back to source client + // + type === TYPES.RES_MOVE_ERR && back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); + }); + } else { + back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); + } } /** * Moves organism's json to nearest server depending on dir parameter - * @param {String} clientId Unique client id + * @param {String} clientId Unique source client id * @param {Number} x Organism x coordinate * @param {Number} y Organism y coordinate * @param {Number} dir Moving direction @@ -165,10 +185,29 @@ class Api extends BaseApi { sock && this.parent.request(sock, TYPES.REQ_MOVE_ORG_FROM_SERVER, clientId, x, y, dir, orgJson); } + /** + * Moves organism back to source client\server + * @param {Array} region Destination region if fromClient === true + * @param {String} clientId Unique source client id + * @param {Number} x Organism x coordinate + * @param {Number} y Organism y coordinate + * @param {Number} dir Moving direction + * @param {String} orgJson Organism's serialized json + * @param {Boolean} fromClient false if organism came from near server + */ + _moveBack(region, clientId, x, y, dir, orgJson, fromClient) { + const newDir = FLIP_DIR[dir]; + const parent = this.parent; + const sock = fromClient ? parent.conns.getConnection(region).sock : parent.aroundServers.getSocket(newDir); + const newClientId = fromClient ? Connections.toId(region) : clientId; + const flipped = Helper.flip(x, y); + sock && parent.request(sock, TYPES.REQ_MOVE_ORG_BACK, newClientId, flipped[0], flipped[1], newDir, orgJson); + } + /** * Sets client active. It means, that sibling active client may * transfer it's organisms to this client - * @param {String} clientId + * @param {String} clientId Unique source client id * @param {Boolean} active */ _setActive(clientId, active) { From 1fbb7998810d0e4affaab152a89a1ee0bd6bd463 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 27 Dec 2017 09:28:49 +0200 Subject: [PATCH 067/291] removed unused onNot() operator in Code2String class. Closed #99 --- client/src/App.js | 8 +-- .../src/manager/plugins/organisms/Organism.js | 2 +- .../plugins/organisms/dos/Code2String.js | 53 ++++++++++--------- server/src/share/Config.js | 8 +-- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/client/src/App.js b/client/src/App.js index 6f12420..85f6589 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -23,11 +23,5 @@ * * @author flatline */ -//const VM = require('./vm/VM'); -//const Operators = require('./manager/plugins/organisms/dos/Operators'); - const Manager = require('./manager/Manager'); -(window.man = new Manager()).run(); -//setTimeout(() => window.man.stop(), 2000); -//window.VM = VM; -//window.Operators = Operators; \ No newline at end of file +(window.man = new Manager()).run(); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 86e335b..e1eb4ad 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -174,7 +174,7 @@ class Organism extends Observer { this._item = null; this._mem = null; this.vm && this.vm.destroy(); - this.vm = null; + this.vm = null; this._codeEndCb = null; super.destroy(); diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index ccf43ce..662796d 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -30,26 +30,26 @@ class Code2String { 1 : this._onCondition.bind(this), 2 : this._onLoop.bind(this), 3 : this._onOperator.bind(this), - 4 : this._onNot.bind(this), + //4 : this._onNot.bind(this), //5 : this._onPi.bind(this), //6 : this._onTrig.bind(this), - 5 : this._onLookAt.bind(this), - 6 : this._onEatLeft.bind(this), - 7 : this._onEatRight.bind(this), - 8 : this._onEatUp.bind(this), - 9 : this._onEatDown.bind(this), - 10: this._onStepLeft.bind(this), - 11: this._onStepRight.bind(this), - 12: this._onStepUp.bind(this), - 13: this._onStepDown.bind(this), - 14: this._onFromMem.bind(this), - 15: this._onToMem.bind(this), - 16: this._onMyX.bind(this), - 17: this._onMyY.bind(this), - 18: this._onCheckLeft.bind(this), - 19: this._onCheckRight.bind(this), - 20: this._onCheckUp.bind(this), - 21: this._onCheckDown.bind(this) + 4 : this._onLookAt.bind(this), + 5 : this._onEatLeft.bind(this), + 6 : this._onEatRight.bind(this), + 7 : this._onEatUp.bind(this), + 8 : this._onEatDown.bind(this), + 9 : this._onStepLeft.bind(this), + 10: this._onStepRight.bind(this), + 11: this._onStepUp.bind(this), + 12: this._onStepDown.bind(this), + 13: this._onFromMem.bind(this), + 14: this._onToMem.bind(this), + 15: this._onMyX.bind(this), + 16: this._onMyY.bind(this), + 17: this._onCheckLeft.bind(this), + 18: this._onCheckRight.bind(this), + 19: this._onCheckUp.bind(this), + 20: this._onCheckDown.bind(this) }; this._OPERATORS_CB_LEN = Object.keys(this._OPERATORS_CB).length; /** @@ -80,6 +80,9 @@ class Code2String { this._OPERATORS_CB = null; this._CONDITIONS = null; this._OPERATORS = null; + this._offsets = null; + delete this._manager.api.formatCode; + this._manager = null; } format(code, separator = '\n') { @@ -136,10 +139,10 @@ class Code2String { return `v${VAR0(num)}=${isConst ? Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : ('v' + var1)}`; } - - _onFunc(num) { - return ''; - } + // + // _onFunc(num) { + // return ''; + // } _onCondition(num, line, lines) { const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); @@ -158,9 +161,9 @@ class Code2String { return `v${VAR0(num)}=v${VAR1(num)}${this._OPERATORS[Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS)]}v${VAR2(num)}`; } - _onNot(num) { - return `v${VAR0(num)}=+!v${VAR1(num)}`; - } + // _onNot(num) { + // return `v${VAR0(num)}=+!v${VAR1(num)}`; + // } //_onPi(num) { // return `v${VAR0(num)}=Math.PI`; diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 32cd12b..7a63c85 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -36,7 +36,7 @@ ServerConfig.init({ * {Number} Port number for connecting with server. This value will be * passed to the server during creation */ - port: 8301, + port: 8100, /** * {Boolean} Means, that this server will be run in distributed mode. And * will be connected with near servers (up...left). false, means, that @@ -46,11 +46,11 @@ ServerConfig.init({ /** * {String} Host address of server above. Shouldn't contain port */ - upHost: 'ws://192.168.31.176', + upHost: 'ws://127.0.0.1', /** * {Number} Port number of server above. */ - upPort: 8201, + upPort: 8200, /** * {String} Host address of server on the right. Shouldn't contain port */ @@ -66,7 +66,7 @@ ServerConfig.init({ /** * {Number} Port number of server below */ - downPort: 8100, + downPort: 8102, /** * {String} Host address of server on the left. Shouldn't contain port */ From 3b4e9296a3253da3b13d13bcd424707e47c382f3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 27 Dec 2017 19:53:23 +0200 Subject: [PATCH 068/291] added Config helper class for working with configurations in tests #83 added test for send organism back to source client #83 --- client/src/manager/ManagerSpec.js | 182 +++++++++++------- .../src/manager/plugins/organisms/Organism.js | 2 +- common/tests/Config.js | 37 ++++ 3 files changed, 154 insertions(+), 67 deletions(-) create mode 100644 common/tests/Config.js diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 0a4c8ca..434a0eb 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -11,6 +11,7 @@ describe("client/src/manager/Manager", () => { const Console = require('./../../../client/src/share/Console'); const SConsole = require('./../../../server/src/share/Console'); const THelper = require('./../../../common/tests/Helper'); + const ConfigHelper = require('./../../../common/tests/Config'); const World = require('./../../../client/src/view/World').World; const Manager = require('./Manager'); const emptyFn = () => {}; @@ -593,27 +594,9 @@ describe("client/src/manager/Manager", () => { }); it('Tests organism moving from client of one server to client of other server', (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const energy = OConfig.orgStartEnergy; - const width = Config.worldWidth; - const height = Config.worldHeight; - const cport = Config.serverPort; - const chost = Config.serverHost; - const cycl = Config.worldCyclical; - const sport = SConfig.port; - const sdport = SConfig.downPort; - const suport = SConfig.upPort; - const maxConns = SConfig.maxConnections; - const distrib = SConfig.modeDistributed; - const iters = OConfig.codeIterationsPerOnce; - const upHost = SConfig.upHost; - const rightHost = SConfig.rightHost; - const downHost = SConfig.downHost; - const leftHost = SConfig.leftHost; + const ocfg = new ConfigHelper(OConfig); + const cfg = new ConfigHelper(Config); + const scfg = new ConfigHelper(SConfig); const freePos = World.prototype.getFreePos; let iterated1 = 0; let iterated2 = 0; @@ -624,27 +607,9 @@ describe("client/src/manager/Manager", () => { waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldWidth = width; - Config.worldHeight = height; - SConfig.port = sport; - SConfig.downPort = sdport; - SConfig.upPort = suport; - Config.serverPort = cport; - Config.serverHost = chost; - SConfig.maxConnections = maxConns; - Config.worldCyclical = cycl; - SConfig.modeDistributed = distrib; - OConfig.codeIterationsPerOnce = iters; - SConfig.upHost = upHost; - SConfig.rightHost = rightHost; - SConfig.downHost = downHost; - SConfig.leftHost = leftHost; + ocfg.reset(); + scfg.reset(); + cfg.reset(); done(); }); }); @@ -652,36 +617,36 @@ describe("client/src/manager/Manager", () => { }); }; - SConfig.upHost = SERVER_HOST; - SConfig.rightHost = SERVER_HOST; - SConfig.downHost = SERVER_HOST; - SConfig.leftHost = SERVER_HOST; - OConfig.codeIterationsPerOnce = 1; - SConfig.modeDistributed = true; - SConfig.maxConnections = 1; - SConfig.port = 3000; - SConfig.downPort = 3001; + scfg.set('upHost', SERVER_HOST); + scfg.set('rightHost', SERVER_HOST); + scfg.set('downHost', SERVER_HOST); + scfg.set('leftHost', SERVER_HOST); + ocfg.set('codeIterationsPerOnce', 1); + scfg.set('modeDistributed', true); + scfg.set('maxConnections', 1); + scfg.set('port', 3000); + scfg.set('downPort', 3001); const server1 = new Server(); // up server - SConfig.port = 3001; - SConfig.upPort = 3000; - SConfig.downPort = 1001; + scfg.set('port', 3001); + scfg.set('upPort', 3000); + scfg.set('downPort', 1001); const server2 = new Server(); // down server - Config.worldWidth = 10; - Config.worldHeight = 10; - Config.serverPort = 3000; - Config.serverHost = SERVER_HOST; + cfg.set('worldWidth', 10); + cfg.set('worldHeight', 10); + cfg.set('serverPort', 3000); + cfg.set('serverHost', SERVER_HOST); const man1 = new Manager(false); delete Config.organisms; delete Config.status; - Config.serverPort = 3001; + cfg.set('serverPort', 3001); const man2 = new Manager(false); - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgStartEnergy = 10000; - Config.worldCyclical = false; + ocfg.set('orgStartAmount', 1); + ocfg.set('orgRainMutationPeriod', 0); + ocfg.set('orgCloneMutationPercent',0); + ocfg.set('orgEnergySpendPeriod', 0); + ocfg.set('orgClonePeriod', 0); + ocfg.set('orgStartEnergy', 10000); + cfg.set('worldCyclical', false); World.prototype.getFreePos = () => {return {x: 1, y: 9}}; man1.on(EVENTS.ITERATION, () => { @@ -703,4 +668,89 @@ describe("client/src/manager/Manager", () => { }); }); }); + + it('Tests organism moving back from client of near server', (done) => { + const ocfg = new ConfigHelper(OConfig); + const cfg = new ConfigHelper(Config); + const scfg = new ConfigHelper(SConfig); + const freePos = World.prototype.getFreePos; + let iterated1 = 0; + let iterated2 = 0; + let org1 = null; + let destroyFlag = false; + let stepInFlag = false; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { + World.prototype.getFreePos = freePos; + ocfg.reset(); + scfg.reset(); + cfg.reset(); + done(); + }); + }); + }); + }); + }; + + scfg.set('upHost', SERVER_HOST); + scfg.set('rightHost', SERVER_HOST); + scfg.set('downHost', SERVER_HOST); + scfg.set('leftHost', SERVER_HOST); + ocfg.set('codeIterationsPerOnce', 1); + scfg.set('modeDistributed', true); + scfg.set('maxConnections', 1); + scfg.set('port', 3000); + scfg.set('downPort', 3001); + const server1 = new Server(); // up server + scfg.set('port', 3001); + scfg.set('upPort', 3000); + scfg.set('downPort', 1001); + const server2 = new Server(); // down server + cfg.set('worldWidth', 10); + cfg.set('worldHeight', 10); + cfg.set('serverPort', 3000); + cfg.set('serverHost', SERVER_HOST); + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + cfg.set('serverPort', 3001); + const man2 = new Manager(false); + ocfg.set('orgStartAmount', 1); + ocfg.set('orgRainMutationPeriod', 0); + ocfg.set('orgCloneMutationPercent',0); + ocfg.set('orgEnergySpendPeriod', 0); + ocfg.set('orgClonePeriod', 0); + ocfg.set('orgStartEnergy', 10000); + cfg.set('worldCyclical', false); + World.prototype.getFreePos = () => {return {x: 1, y: 0}}; + + man1.on(EVENTS.ITERATION, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + expect(man2.organisms.size).toBe(1); + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + man1.on(EVENTS.KILL_ORGANISM, () => { + destroyFlag = true; + }); + man2.on(EVENTS.STEP_IN, () => { + stepInFlag = true; + }); + } else if (destroyFlag && stepInFlag) { + destroyFlag = false; + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Servers'} + iterated1++; + }); + man2.on(EVENTS.ITERATION, () => iterated2++); + + waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { + waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { + man1.run(man2.run); + }); + }); + }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 86e335b..e1eb4ad 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -174,7 +174,7 @@ class Organism extends Observer { this._item = null; this._mem = null; this.vm && this.vm.destroy(); - this.vm = null; + this.vm = null; this._codeEndCb = null; super.destroy(); diff --git a/common/tests/Config.js b/common/tests/Config.js new file mode 100644 index 0000000..6ca1f91 --- /dev/null +++ b/common/tests/Config.js @@ -0,0 +1,37 @@ +/** + * Helper class for managing different configurations. It's useful + * for setting temporary config parameters to config object and resetting + * them later back. Is used in tests. + * + * Usage: + * CConfig.prop = 1; + * const cfg = new Config(CConfig); // CConfig.prop = 1 + * cfg.set('prop', 2); + * + * @author flatline + */ +const _set = require('lodash/set'); +const _get = require('lodash/get'); +const _merge = require('lodash/merge'); + +class Config { + constructor(cfgObj) { + this._tmpCfg = {}; + this._cfg = cfgObj; + } + + set(prop, val) { + const tmpCfg = this._tmpCfg; + const cfg = this._cfg; + + _get(tmpCfg, prop) === undefined && _set(tmpCfg, prop, _get(cfg, prop)); + _set(cfg, prop, val); + } + + reset() { + _merge(this._cfg, this._tmpCfg); + this._tmpCfg = {}; + } +} + +module.exports = Config; \ No newline at end of file From b2e35ea6b36bc52339d3ba67f762006521f7e8c4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 27 Dec 2017 23:58:56 +0200 Subject: [PATCH 069/291] added test for checking move organism back to source client #83 fixed issues related to move organism back #98 --- client/src/manager/ManagerSpec.js | 12 +++++------ .../src/manager/plugins/client/plugins/Api.js | 9 ++++----- server/src/server/plugins/Api.js | 20 +++++++++---------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 434a0eb..f494266 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -679,6 +679,7 @@ describe("client/src/manager/Manager", () => { let org1 = null; let destroyFlag = false; let stepInFlag = false; + let stepInBack = false; const destroy = () => { man1.destroy(() => { man2.destroy(() => { @@ -732,13 +733,10 @@ describe("client/src/manager/Manager", () => { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() - man1.on(EVENTS.KILL_ORGANISM, () => { - destroyFlag = true; - }); - man2.on(EVENTS.STEP_IN, () => { - stepInFlag = true; - }); - } else if (destroyFlag && stepInFlag) { + man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); + man1.on(EVENTS.STEP_IN, () => stepInBack = true); + man2.on(EVENTS.STEP_IN, () => stepInFlag = true); + } else if (destroyFlag && stepInFlag && stepInBack) { destroyFlag = false; destroy(); } diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 7d9f88d..30a1cb1 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -12,8 +12,8 @@ class Api extends BaseApi { constructor(client) { super(client); - this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this, false); - this.api[TYPES.REQ_MOVE_ORG_BACK] = this._stepIn.bind(this, true); + this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this); + this.api[TYPES.REQ_MOVE_ORG_BACK] = this._stepIn.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setActive.bind(this); } @@ -24,7 +24,6 @@ class Api extends BaseApi { /** * Is called if organism is move in from other Manager (world) - * @param {Boolean} back true, if organism is sent back * @param {String} reqId Unique request id * @param {String} clientId Unique client id within current server * @param {Number} x Current org X position @@ -33,10 +32,10 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _stepIn(back, reqId, clientId, x, y, dir, orgJson) { + _stepIn(reqId, clientId, x, y, dir, orgJson) { const ret = {ret: true}; this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson, ret); - !back && this.parent.response(this.sock, ret.ret ? TYPES.RES_MOVE_OK : TYPES.RES_MOVE_ERR, reqId, clientId); + this.parent.response(this.sock, ret.ret ? TYPES.RES_MOVE_OK : TYPES.RES_MOVE_ERR, reqId, clientId); } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 02873d2..caf7be5 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -21,9 +21,9 @@ class Api extends BaseApi { super(parent); const servers = parent.aroundServers; - this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrgFromClient.bind(this, false); - this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this); - this.api[TYPES.REQ_MOVE_ORG_BACK] = this._onMoveOrgFromClient.bind(this, true); + this.api[TYPES.REQ_MOVE_ORG] = this._onMoveOrgFromClient.bind(this); + this.api[TYPES.REQ_MOVE_ORG_FROM_SERVER] = this._onMoveOrgFromServer.bind(this, false); + this.api[TYPES.REQ_MOVE_ORG_BACK] = this._onMoveOrgFromServer.bind(this, true); this.api[TYPES.REQ_GET_ID] = this._onGetId.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._onSetNearServer.bind(this); @@ -52,6 +52,7 @@ class Api extends BaseApi { /** * Moves organism from near server to current server + * @param {Boolean} back true, if the organism is sent back * @param {Number} reqId Unique request id. Needed for response * @param {String} clientId Unique source client id * @param {Number} x Current org X position @@ -60,16 +61,15 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _onMoveOrgFromServer(reqId, clientId, x, y, dir, orgJson) { + _onMoveOrgFromServer(back, reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const conns = this.parent.conns; - this._moveToClient(false, Connections.toId(conns.oppositeRegion(reg, dir)), x, y, dir, orgJson, false); + this._moveToClient(back, Connections.toId(conns.oppositeRegion(reg, dir)), x, y, dir, orgJson, false); } /** * Moves organism from one client to another or to nearest server if * it's connected to current one - * @param {Boolean} back true, if the organism is sent back * @param {Number} reqId Unique request id. Needed for response * @param {String} clientId Unique source client id * @param {Number} x Current org X position @@ -78,7 +78,7 @@ class Api extends BaseApi { * @param {String} orgJson Organism's serialized json * @api */ - _onMoveOrgFromClient(back, reqId, clientId, x, y, dir, orgJson) { + _onMoveOrgFromClient(reqId, clientId, x, y, dir, orgJson) { const reg = Connections.toRegion(clientId); const side = this.parent.conns.side - 1; // @@ -87,7 +87,7 @@ class Api extends BaseApi { // if (dir === DIR.UP && reg[1] > 0 || dir === DIR.RIGHT && reg[0] < side || dir === DIR.DOWN && reg[1] < side || dir === DIR.LEFT && reg[0] > 0) { - this._moveToClient(back, clientId, x, y, dir, orgJson); + this._moveToClient(false, clientId, x, y, dir, orgJson); return; } // @@ -165,10 +165,10 @@ class Api extends BaseApi { // // No free space for organism - send it back to source client // - type === TYPES.RES_MOVE_ERR && back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); + type === TYPES.RES_MOVE_ERR && !back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); }); } else { - back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); + !back && this._moveBack(region, clientId, x, y, dir, orgJson, fromClient); } } From ffae0ae5ab2a4edf189e3ba693ac67cb8ceeafd3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 28 Dec 2017 19:05:23 +0200 Subject: [PATCH 070/291] added test for returning organism back #83 --- client/src/manager/ManagerSpec.js | 75 +++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index f494266..0720145 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -751,4 +751,79 @@ describe("client/src/manager/Manager", () => { }); }); }); + + it('Tests organism moving back from client of near server (with no clients)', (done) => { + const ocfg = new ConfigHelper(OConfig); + const cfg = new ConfigHelper(Config); + const scfg = new ConfigHelper(SConfig); + const freePos = World.prototype.getFreePos; + let iterated1 = 0; + let iterated2 = 0; + let org1 = null; + let destroyFlag = false; + let stepInBack = false; + const destroy = () => { + man1.destroy(() => { + //man2.destroy(() => { + waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { + World.prototype.getFreePos = freePos; + ocfg.reset(); + scfg.reset(); + cfg.reset(); + done(); + }); + }); + //}); + }); + }; + + scfg.set('upHost', SERVER_HOST); + scfg.set('rightHost', SERVER_HOST); + scfg.set('downHost', SERVER_HOST); + scfg.set('leftHost', SERVER_HOST); + ocfg.set('codeIterationsPerOnce', 1); + scfg.set('modeDistributed', true); + scfg.set('maxConnections', 1); + scfg.set('port', 3000); + scfg.set('downPort', 3001); + const server1 = new Server(); // up server + scfg.set('port', 3001); + scfg.set('upPort', 3000); + scfg.set('downPort', 1001); + const server2 = new Server(); // down server + cfg.set('worldWidth', 10); + cfg.set('worldHeight', 10); + cfg.set('serverPort', 3000); + cfg.set('serverHost', SERVER_HOST); + const man1 = new Manager(false); + ocfg.set('orgStartAmount', 1); + ocfg.set('orgRainMutationPeriod', 0); + ocfg.set('orgCloneMutationPercent',0); + ocfg.set('orgEnergySpendPeriod', 0); + ocfg.set('orgClonePeriod', 0); + ocfg.set('orgStartEnergy', 10000); + cfg.set('worldCyclical', false); + World.prototype.getFreePos = () => {return {x: 1, y: 5}}; + + man1.on(EVENTS.ITERATION, () => { + if (iterated1 > 0 && org1 === null) { + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); + man1.on(EVENTS.STEP_IN, () => stepInBack = true); + } else if (destroyFlag && stepInBack) { + destroyFlag = false; + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Servers'} + iterated1++; + }); + + waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { + waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { + man1.run(); + }); + }); + }); }); \ No newline at end of file From 65757ebd9edc8447118fb2e563e23a22f647f7a2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 28 Dec 2017 19:29:27 +0200 Subject: [PATCH 071/291] addition to tests for returning back from destination client #83 --- client/src/manager/ManagerSpec.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 0720145..70dd677 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -758,7 +758,6 @@ describe("client/src/manager/Manager", () => { const scfg = new ConfigHelper(SConfig); const freePos = World.prototype.getFreePos; let iterated1 = 0; - let iterated2 = 0; let org1 = null; let destroyFlag = false; let stepInBack = false; @@ -811,9 +810,12 @@ describe("client/src/manager/Manager", () => { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); - man1.on(EVENTS.STEP_IN, () => stepInBack = true); + man1.on(EVENTS.STEP_IN, () => { + stepInBack = true; + }); } else if (destroyFlag && stepInBack) { - destroyFlag = false; + stepInBack = false; + expect(man1.organisms.size).toBe(2); destroy(); } if (iterated1 > 10000) {throw 'Error sending organism between Servers'} From 85663da24b2725d01ab8d469e81e1aa9fe78dab4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 29 Dec 2017 00:09:34 +0200 Subject: [PATCH 072/291] fixed an issue of blocked transfer between clients on one server --- client/src/manager/ManagerSpec.js | 4 +--- client/src/manager/plugins/organisms/Config.js | 8 ++++---- client/src/share/Config.js | 2 +- server/src/server/plugins/Api.js | 8 ++++---- server/src/share/Config.js | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 70dd677..224e2d5 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -810,9 +810,7 @@ describe("client/src/manager/Manager", () => { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); - man1.on(EVENTS.STEP_IN, () => { - stepInBack = true; - }); + man1.on(EVENTS.STEP_IN, () => stepInBack = true); } else if (destroyFlag && stepInBack) { stepInBack = false; expect(man1.organisms.size).toBe(2); diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index c1c5aa6..2d26476 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -65,12 +65,12 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 500, + orgRainMutationPeriod: 1000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.02, + orgRainMutationPercent: 0.01, /** * {Number} Amount of organisms we have to create on program start */ @@ -80,7 +80,7 @@ const Config = { * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 100000, + orgStartEnergy: 1000000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB @@ -152,7 +152,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 10, + codeYieldPeriod: 5, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. diff --git a/client/src/share/Config.js b/client/src/share/Config.js index bbe468e..8043ec7 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -62,7 +62,7 @@ ClientConfig.init({ * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... */ - worldEnergyDots: 1000, + worldEnergyDots: 10000, /** * {Number} Amount of energy in every block. See worldEnergyDots * config for details. diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index caf7be5..07a86bf 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -236,10 +236,10 @@ class Api extends BaseApi { const sock = server.conns.getConnection(region).sock; const servers = this.parent.aroundServers; const side = conns.side - 1; - const activeUp = !!conns.getConnection(_get(conns.upRegion (region), 'sock')) || region[1] === 0 && servers && servers.hasSocket(DIR.UP); - const activeRight = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[0] === side && servers && servers.hasSocket(DIR.RIGHT); - const activeDown = !!conns.getConnection(_get(conns.downRegion(region), 'sock')) || region[1] === side && servers && servers.hasSocket(DIR.DOWN); - const activeLeft = !!conns.getConnection(_get(conns.leftRegion(region), 'sock')) || region[0] === 0 && servers && servers.hasSocket(DIR.LEFT); + const activeUp = !!_get(conns.getConnection(conns.upRegion (region)), 'sock') || region[1] === 0 && servers && servers.hasSocket(DIR.UP); + const activeRight = !!_get(conns.getConnection(conns.downRegion(region)), 'sock') || region[0] === side && servers && servers.hasSocket(DIR.RIGHT); + const activeDown = !!_get(conns.getConnection(conns.downRegion(region)), 'sock') || region[1] === side && servers && servers.hasSocket(DIR.DOWN); + const activeLeft = !!_get(conns.getConnection(conns.leftRegion(region)), 'sock') || region[0] === 0 && servers && servers.hasSocket(DIR.LEFT); server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.UP, activeUp); server.request(sock, TYPES.REQ_SET_NEAR_ACTIVE, DIR.RIGHT, activeRight); diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 7a63c85..9ed76ee 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -36,7 +36,7 @@ ServerConfig.init({ * {Number} Port number for connecting with server. This value will be * passed to the server during creation */ - port: 8100, + port: 8301, /** * {Boolean} Means, that this server will be run in distributed mode. And * will be connected with near servers (up...left). false, means, that From c27931bb42564fd5bfc32e29317c976780b071c0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 29 Dec 2017 15:07:50 +0200 Subject: [PATCH 073/291] fixed issue with incorrect closing of connection with client --- client/src/manager/ManagerSpec.js | 13 +++++++------ client/src/manager/plugins/organisms/Config.js | 2 +- common/src/plugins/Request.js | 13 +++++++++---- server/src/server/plugins/Api.js | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 224e2d5..e665782 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -208,12 +208,13 @@ describe("client/src/manager/Manager", () => { const man = new Manager(false); expect(man.clientId).toBe(null); - server.run(); - man.run(() => { - expect(man.active).toBe(true); - expect(man.clientId !== null).toBe(true); - man.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); + waitEvent(server, SEVENTS.RUN, () => server.run(), () => { + man.run(() => { + expect(man.active).toBe(true); + expect(man.clientId !== null).toBe(true); + man.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); + }); }); }); }); diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 2d26476..de0c84a 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 1000, + codeIterationsPerOnce: 100, }; module.exports = Config; \ No newline at end of file diff --git a/common/src/plugins/Request.js b/common/src/plugins/Request.js index eb519cf..a39a6cc 100644 --- a/common/src/plugins/Request.js +++ b/common/src/plugins/Request.js @@ -5,10 +5,11 @@ * * @author flatline */ -const Helper = require('./../Helper'); -const Config = require('./../../../client/src/share/Config').Config; -const MASKS = require('./../net/Requests').MASKS; -const Console = require(`./../../../${Config.modeNodeJs ? 'server' : 'client'}/src/share/Console`); +const WebSocket = require('ws'); +const Helper = require('./../Helper'); +const Config = require('./../../../client/src/share/Config').Config; +const MASKS = require('./../net/Requests').MASKS; +const Console = require(`./../../../${Config.modeNodeJs ? 'server' : 'client'}/src/share/Console`); class Request { /** @@ -73,6 +74,10 @@ class Request { const cb = Helper.isFunc(params[params.length - 1]) ? params.pop() : null; const reqId = Helper.getId(); + if (sock.readyState > WebSocket.OPEN) { + this._onSendErr('Request is interrupted, because connection has closed'); + return reqId; + } cb && (this._requests[reqId] = cb); try { sock.send(JSON.stringify([type, (reqId | MASKS.REQ_MASK) >>> 0].concat(params)), this._onSendErrCb); diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 07a86bf..8d6a9ff 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -280,7 +280,7 @@ class Api extends BaseApi { // server is full of other clients and there is no free slot for this // if (clientId === false) {return} - if (dir === DIR.NO) { + if (dir === DIR.NO || dir === clientId) { this._activateAround(Connections.toRegion(clientId), false); return; } From 6f1c4a1a64df96dc2a4fa678b127714382c310f9 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 30 Dec 2017 00:52:58 +0200 Subject: [PATCH 074/291] added more cool method of functional testing. See Helper.testQ() method #83 refactored Helper.compare() to _.isEqual() --- client/src/manager/ManagerSpec.js | 40 ++++++---------- .../plugins/organisms/dos/OrganismSpec.js | 16 +++---- client/src/vm/VMSpec.js | 28 +++++------ common/tests/Helper.js | 47 ++++++++++++++----- server/src/server/ConnectionsSpec.js | 8 ++-- 5 files changed, 75 insertions(+), 64 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index e665782..f5b601b 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -17,6 +17,7 @@ describe("client/src/manager/Manager", () => { const emptyFn = () => {}; const waitEvent = THelper.waitEvent; const wait = THelper.wait; + const testQ = THelper.testQ; const host = Config.serverHost; const port = SConfig.port; const maxConns = SConfig.maxConnections; @@ -503,6 +504,7 @@ describe("client/src/manager/Manager", () => { let amount = 0; let waitObj = {done: false}; let count = 0; + const onDone = () => ++count === 2 && (waitObj.done = true); let man1; let man2; let oldId; @@ -515,31 +517,19 @@ describe("client/src/manager/Manager", () => { delete Config.status; man2 = new Manager(false); - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { - man1.run(() => ++count === 2 && (waitObj.done = true)); - man2.run(() => ++count === 2 && (waitObj.done = true)); - wait(waitObj, () => { - man1.stop(() => { - expect(man1.clientId).toBe(null); - oldId = man1.clientId; - man1.run(() => { - expect(man1.clientId).not.toBe(null); - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - man1.destroy(); - man2.destroy(); - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }); - }); - }); - }); + testQ(done, + [server, SEVENTS.RUN, () => server.run(), () => {man1.run(onDone); man2.run(onDone)}], + [waitObj], + [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], + [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], + [server, SEVENTS.CLOSE, () => man1.destroy(), () => {}], + [server, SEVENTS.CLOSE, () => man2.destroy(), () => {}], + [server, SEVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + }] + ); }); it("Tests many connections/disconnections of Manager to the server", (done) => { diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 6c82912..ad78b56 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -2,12 +2,10 @@ // This spec covers two classes "Organism" and "OrganismDos" // describe("client/src/organism/OrganismDos", () => { - let OrganismDos = require('./Organism'); - let Config = require('./../../../../share/Config').Config; - let OConfig = require('./../../../../manager/plugins/organisms/Config'); - let api = require('./../../../../share/Config').api; - let THelper = require('./../../../../../../common/tests/Helper'); - let cls; + const eq = require('lodash/isEqual'); + const OrganismDos = require('./Organism'); + const OConfig = require('./../../../../manager/plugins/organisms/Config'); + const api = require('./../../../../share/Config').api; it("Checking organism creation", () => { let org = new OrganismDos(0, 1, 2, true, null, () => {}); @@ -17,7 +15,7 @@ describe("client/src/organism/OrganismDos", () => { expect(org.y).toEqual(2); expect(org.item).toEqual(null); expect(org.alive).toEqual(true); - expect(THelper.compare(org.mutationProbs, OConfig.orgMutationProbs)).toEqual(true); + expect(eq(org.mutationProbs, OConfig.orgMutationProbs)).toEqual(true); expect(org.mutationPeriod === OConfig.orgRainMutationPeriod).toEqual(true); expect(org.mutationPercent === OConfig.orgRainMutationPercent).toEqual(true); expect(org.cloneMutationPercent === OConfig.orgCloneMutationPercent).toEqual(true); @@ -49,12 +47,12 @@ describe("client/src/organism/OrganismDos", () => { expect(org.vm.size === parent.vm.size).toEqual(true); expect(org.energy === parent.energy).toEqual(true); expect(org.color === parent.color).toEqual(true); - expect(THelper.compare(org.mutationProbs, parent.mutationProbs)).toEqual(true); + expect(eq(org.mutationProbs, parent.mutationProbs)).toEqual(true); expect(org.cloneMutationPercent === parent.cloneMutationPercent).toEqual(true); expect(org.mutationPeriod === parent.mutationPeriod).toEqual(true); expect(org.mutationPercent === parent.mutationPercent).toEqual(true); expect(org.cloneEnergyPercent === parent.cloneEnergyPercent).toEqual(true); - expect(THelper.compare(org.mem, parent.mem)).toEqual(true); + expect(eq(org.mem, parent.mem)).toEqual(true); expect(org.changes === 1).toEqual(true); expect(org.iterations === 0).toEqual(true); diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 1ccff90..6073706 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,14 +1,12 @@ describe("client/src/organism/VM", () => { - let Observer = require('./../../../common/src/Observer'); - let Helper = require('./../../../common/src/Helper'); - let THelper = require('./../../../common/tests/Helper'); - let Config = require('./../share/Config').Config; - let OConfig = require('./../manager/plugins/organisms/Config'); - let api = require('./../share/Config').api; - let VM = require('./VM'); - let Num = require('./Num'); - let Operators = require('./Operators'); - let cls = null; + const eq = require('lodash/isEqual'); + const Observer = require('./../../../common/src/Observer'); + const Helper = require('./../../../common/src/Helper'); + const OConfig = require('./../manager/plugins/organisms/Config'); + const api = require('./../share/Config').api; + const VM = require('./VM'); + const Num = require('./Num'); + const Operators = require('./Operators'); it("Checking vm creation", () => { let flag = false; @@ -149,7 +147,7 @@ describe("client/src/organism/VM", () => { jsvm2._code.push(17000004); jsvm1.crossover(jsvm2); - expect(THelper.compare(jsvm1.code, [ + expect(eq(jsvm1.code, [ 16000000, 17000001, 17000002, @@ -190,7 +188,7 @@ describe("client/src/organism/VM", () => { jsvm2._code.push(17000004); jsvm1.crossover(jsvm2); - expect(THelper.compare(jsvm1.code, [ + expect(eq(jsvm1.code, [ 16000000, 17000001, 16000003, @@ -229,7 +227,7 @@ describe("client/src/organism/VM", () => { jsvm2._code.push(17000004); jsvm1.crossover(jsvm2); - expect(THelper.compare(jsvm1.code, [ + expect(eq(jsvm1.code, [ 16000000, 17000001, 17000002, @@ -274,7 +272,7 @@ describe("client/src/organism/VM", () => { jsvm2._code.push(17000003); jsvm1.crossover(jsvm2); - expect(THelper.compare(jsvm1.code, [ + expect(eq(jsvm1.code, [ 17000001, 17000002 ])).toEqual(true); @@ -304,7 +302,7 @@ describe("client/src/organism/VM", () => { jsvm1._code.push(16000003); jsvm1.crossover(jsvm2); - expect(THelper.compare(jsvm1.code, [ + expect(eq(jsvm1.code, [ 16000000, 16000003, ])).toEqual(true); diff --git a/common/tests/Helper.js b/common/tests/Helper.js index 96cfd56..204df87 100644 --- a/common/tests/Helper.js +++ b/common/tests/Helper.js @@ -3,18 +3,9 @@ * * @author flatline */ -class Helper { - /** - * Compares two arrays only on first level - * @param {Array} arr1 - * @param {Array} arr2 - * @returns {Boolean} - */ - static compare(arr1, arr2) { - if (arr1.length !== arr2.length) {return false} - return !arr1.some((a) => arr2.indexOf(a) === -1) - } +const each = require('lodash/each'); +class Helper { /** * Waiting for obj.done property to be true and calls cb() callback * after that. If property is not changed, then error will be thrown @@ -59,6 +50,40 @@ class Helper { waitObj.done && waitCb() || Helper.wait(waitObj, waitCb); } + + /** + * Runs all testing tasks of a queue one by one in a synchronous manner. + * Testing task is another array of four or two elements - event parameters with + * a function at the end. Four items array is used with waitEvent() and two + * items array is used with wait() + * @param {Function} done Done callback + * @param {Array} queue Testing tasks + */ + static testQ(done, ...queue) { + const len = queue.length; + let i = 0; + let iterate = (q) => { + if (q.length === 4) { + Helper.waitEvent(q[0], q[1], q[2], () => { + q[3](); + i < len && iterate(queue[i++]) || done(); + }); + } else if (q.length === 2) { + Helper.wait(q[0], () => { + q[1](); + i < len && iterate(queue[i++]) || done(); + }); + } else if (q.length === 1) { + Helper.wait(q[0], () => { + i < len && iterate(queue[i++]) || done(); + }); + } + + return true; + }; + + len && iterate(queue[i++]) || done(); + } } module.exports = Helper; \ No newline at end of file diff --git a/server/src/server/ConnectionsSpec.js b/server/src/server/ConnectionsSpec.js index 83e4aa5..bf1dc1e 100644 --- a/server/src/server/ConnectionsSpec.js +++ b/server/src/server/ConnectionsSpec.js @@ -1,6 +1,6 @@ describe("server/src/server/Connections", () => { const Connections = require('./Connections'); - let THelper = require('./../../../common/tests/Helper'); + const eq = require('lodash/isEqual'); it("Checking Connections instance creation", () => { let cons = new Connections(1); @@ -19,15 +19,15 @@ describe("server/src/server/Connections", () => { let cons = new Connections(1); let region = cons.getFreeRegion(); - expect(THelper.compare(region, [0, 0])).toEqual(true); + expect(eq(region, [0, 0])).toEqual(true); expect(Connections.toId(region)).toEqual('0-0'); expect(Connections.toId([1,1])).toEqual('1-1'); expect(Connections.toId([0,0])).toEqual('0-0'); cons.destroy(); }); it("Checking toRegion() method", () => { - expect(THelper.compare(Connections.toRegion('1-1'), [1,1])).toEqual(true); - expect(THelper.compare(Connections.toRegion('1-0'), [1,0])).toEqual(true); + expect(eq(Connections.toRegion('1-1'), [1,1])).toEqual(true); + expect(eq(Connections.toRegion('1-0'), [1,0])).toEqual(true); }); it("Checking upRegion() method", () => { let cons = new Connections(1); From 143b5f958b1366bcbccf838bee4a10287297b1ee Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 30 Dec 2017 10:53:42 +0200 Subject: [PATCH 075/291] from now near client will be at the right side (not below) fixed an issue with crashing chrome devTools window --- client/src/manager/plugins/organisms/Config.js | 2 +- server/src/server/Connections.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 2d26476..de0c84a 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 1000, + codeIterationsPerOnce: 100, }; module.exports = Config; \ No newline at end of file diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index 243230d..9fedd51 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -151,8 +151,8 @@ class Connections { const conns = this.conns; const side = this._side; - for (let col = 0; col < side; col++) { - for (let row = 0; row < side; row++) { + for (let row = 0; row < side; row++) { + for (let col = 0; col < side; col++) { if (conns[col][row].sock === null) { return [col, row]; } From 945b9939406a5c6cd53ca146c8b8f1fd123f6fc3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 30 Dec 2017 11:44:57 +0200 Subject: [PATCH 076/291] added showing current client's id (coordinates) in a top left corner --- client/src/manager/plugins/status/Status.js | 2 +- server/src/server/Connections.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 2b190bd..991caac 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -80,7 +80,7 @@ class Status extends Configurable { const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - this._manager.hasView && this._manager.canvas.text(5, 15, sips); + this._manager.hasView && this._manager.canvas.text(5, 15, sips + this._manager.clientId); this._onAfterLog(stamp); } diff --git a/server/src/server/Connections.js b/server/src/server/Connections.js index 9fedd51..715e0ef 100644 --- a/server/src/server/Connections.js +++ b/server/src/server/Connections.js @@ -49,9 +49,9 @@ class Connections { */ this._side = side; - for (let col = 0, conns = this.conns; col < this._side; col++) { - conns[col] = (new Array(this._side)).fill(null); - conns[col].forEach((v, i, a) => a[i] = {sock: null}); + for (let row = 0, conns = this.conns; row < this._side; row++) { + conns[row] = (new Array(this._side)).fill(null); + conns[row].forEach((v, i, a) => a[i] = {sock: null}); } } @@ -151,10 +151,10 @@ class Connections { const conns = this.conns; const side = this._side; - for (let row = 0; row < side; row++) { - for (let col = 0; col < side; col++) { - if (conns[col][row].sock === null) { - return [col, row]; + for (let y = 0; y < side; y++) { + for (let x = 0; x < side; x++) { + if (conns[x][y].sock === null) { + return [x, y]; } } } From f09054084a8e04792d6643c89bb46d5cd7458bab Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 30 Dec 2017 13:22:38 +0200 Subject: [PATCH 077/291] small refactoring --- client/src/manager/plugins/organisms/dos/Organisms.js | 4 ++++ client/src/manager/plugins/status/Status.js | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 9dfd06f..86d0916 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -214,6 +214,10 @@ class Organisms extends BaseOrganisms { const org = this.organisms.last.val; org.unserialize(orgJson); org.grabEnergy(OConfig.orgStepEnergySpendPercent); + // + // We have to update organism color + // + this.manager.world.setDot(org.x, org.y, org.color); } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 991caac..f14b20c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -67,6 +67,7 @@ class Status extends Configurable { this._times++; if (stamp - this._stamp < StatusConfig.period) {return} + const man = this._manager; this._onBeforeLog(ips, orgs); const format = Status._format; const orgAmount = orgs.size || 1; @@ -80,7 +81,7 @@ class Status extends Configurable { const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - this._manager.hasView && this._manager.canvas.text(5, 15, sips + this._manager.clientId); + man.hasView && man.canvas.text(5, 15, sips + man.clientId); this._onAfterLog(stamp); } From ba00b7f2a6eeae378c799ba22a75f35bce2ab236 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 30 Dec 2017 23:28:40 +0200 Subject: [PATCH 078/291] fixed critical issue with zombie organisms and returning organisms back --- client/src/manager/plugins/organisms/dos/Organisms.js | 4 +++- common/src/Helper.js | 6 ++++-- server/src/server/plugins/Api.js | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 86d0916..c634be2 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -215,8 +215,10 @@ class Organisms extends BaseOrganisms { org.unserialize(orgJson); org.grabEnergy(OConfig.orgStepEnergySpendPercent); // - // We have to update organism color + // We have to update organism color and coordinates // + org.x = x; + org.y = y; this.manager.world.setDot(org.x, org.y, org.color); } } diff --git a/common/src/Helper.js b/common/src/Helper.js index 62850e2..ecb21ff 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -139,11 +139,13 @@ class Helper { * width=10, height=10, x=3, y=9 -> x=3, y=0 * @param {Number} x X coordinate * @param {Number} y Y coordinate + * @param {Number} dir Moving direction */ - static flip(x, y) { + static flip(x, y, dir) { const xMap = {0: Config.worldWidth - 1, [Config.worldWidth - 1]: 0}; const yMap = {0: Config.worldHeight - 1, [Config.worldHeight - 1]: 0}; - return [xMap[x] ? xMap[x] : x, yMap[y] ? yMap[y] : y]; + + return [(dir === DIR.LEFT || dir === DIR.RIGHT) && xMap[x] ? xMap[x] : x, (dir === DIR.UP || dir === DIR.DOWN) && yMap[y] ? yMap[y] : y]; } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 8d6a9ff..1b41d2e 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -200,7 +200,7 @@ class Api extends BaseApi { const parent = this.parent; const sock = fromClient ? parent.conns.getConnection(region).sock : parent.aroundServers.getSocket(newDir); const newClientId = fromClient ? Connections.toId(region) : clientId; - const flipped = Helper.flip(x, y); + const flipped = Helper.flip(x, y, newDir); sock && parent.request(sock, TYPES.REQ_MOVE_ORG_BACK, newClientId, flipped[0], flipped[1], newDir, orgJson); } From f7fb462cf2ce31cd4472cc7e6f8810c1e898286e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 31 Dec 2017 00:24:17 +0200 Subject: [PATCH 079/291] increased ips font --- client/src/manager/plugins/status/Status.js | 2 +- client/src/view/Canvas.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index f14b20c..1a024a9 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -81,7 +81,7 @@ class Status extends Configurable { const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - man.hasView && man.canvas.text(5, 15, sips + man.clientId); + man.hasView && man.canvas.text(5, 20, sips + man.clientId); this._onAfterLog(stamp); } diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 75cd965..c1d946f 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -23,7 +23,7 @@ class Canvas { this._animate = this._onAnimate.bind(this); this._visualize = true; - this._ctx.font = "13px Consolas"; + this._ctx.font = "18px Consolas"; this._ctx.fillStyle = "white"; this.clear(); window.requestAnimationFrame(this._animate); From 38f48c8b638143dcbb5892803d3e4af0e60c9d1d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 31 Dec 2017 13:52:20 +0200 Subject: [PATCH 080/291] fixed small issue with status padding (iq parameter) --- client/src/manager/plugins/status/Status.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 1a024a9..cc7189c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -75,7 +75,7 @@ class Status extends Configurable { const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 13, 100000 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); const sfit = format(this._fitness, 'fit', orgAmount, 3, 14 ); const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true); const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); From 40d10401954f11d371861b14e1846b9a6172aa79 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 31 Dec 2017 18:01:07 +0200 Subject: [PATCH 081/291] fixed critical issue #100 --- server/src/server/plugins/Api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 1b41d2e..5504f40 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -237,7 +237,7 @@ class Api extends BaseApi { const servers = this.parent.aroundServers; const side = conns.side - 1; const activeUp = !!_get(conns.getConnection(conns.upRegion (region)), 'sock') || region[1] === 0 && servers && servers.hasSocket(DIR.UP); - const activeRight = !!_get(conns.getConnection(conns.downRegion(region)), 'sock') || region[0] === side && servers && servers.hasSocket(DIR.RIGHT); + const activeRight = !!_get(conns.getConnection(conns.rightRegion(region)), 'sock') || region[0] === side && servers && servers.hasSocket(DIR.RIGHT); const activeDown = !!_get(conns.getConnection(conns.downRegion(region)), 'sock') || region[1] === side && servers && servers.hasSocket(DIR.DOWN); const activeLeft = !!_get(conns.getConnection(conns.leftRegion(region)), 'sock') || region[0] === 0 && servers && servers.hasSocket(DIR.LEFT); From fda00a78e5923bc233d4884028774f9c40b8b8e3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 31 Dec 2017 20:51:01 +0200 Subject: [PATCH 082/291] fixed tests #83 --- client/src/manager/ManagerSpec.js | 70 +++++++++++++++---------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index f5b601b..5434b4b 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -320,9 +320,11 @@ describe("client/src/manager/Manager", () => { const percent = OConfig.orgCloneMutationPercent; const period1 = OConfig.orgEnergySpendPeriod; const clone = OConfig.orgClonePeriod; + const width = Config.worldWidth; const height = Config.worldHeight; const energy = OConfig.orgStartEnergy; const server = new Server(); + Config.worldWidth = 400; Config.worldHeight = 400; const man1 = new Manager(false); delete Config.organisms; @@ -343,6 +345,7 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = percent; OConfig.orgRainMutationPeriod = period; OConfig.orgStartAmount = amount; + Config.worldWidth = width; Config.worldHeight = height; done(); }); @@ -356,12 +359,12 @@ describe("client/src/manager/Manager", () => { OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; OConfig.orgStartEnergy = 10000; - World.prototype.getFreePos = () => {return {x: 1, y: 399}}; + World.prototype.getFreePos = () => {return {x: 399, y: 1}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() } else if (man2.organisms.size === 2) { destroy(); } @@ -387,6 +390,7 @@ describe("client/src/manager/Manager", () => { const energy = OConfig.orgStartEnergy; const server = new Server(); Config.worldHeight = 400; + Config.worldWidth = 400; const man1 = new Manager(false); delete Config.organisms; delete Config.status; @@ -422,12 +426,12 @@ describe("client/src/manager/Manager", () => { OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; OConfig.orgStartEnergy = 10000; - World.prototype.getFreePos = () => {return inc++ === 0 && {x: 1, y: 399} || {x: 1, y: 0}}; + World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() man1.on(EVENTS.STEP_OUT, () => { expect(doneInc < 3).toBe(true); ++doneInc; @@ -435,13 +439,13 @@ describe("client/src/manager/Manager", () => { man2.on(EVENTS.STEP_IN, () => { ++doneInc; expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.y).toBe(0); + expect(man1.organisms.first.val.x).toBe(0); }); } else if (org1 !== null && org2 !== null && doneInc === 2) { expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.y).toBe(0); + expect(man1.organisms.first.val.x).toBe(0); expect(man2.organisms.size).toBe(1); - expect(man2.organisms.first.val.y).toBe(0); + expect(man2.organisms.first.val.x).toBe(0); destroy(); doneInc++; } @@ -616,11 +620,11 @@ describe("client/src/manager/Manager", () => { scfg.set('modeDistributed', true); scfg.set('maxConnections', 1); scfg.set('port', 3000); - scfg.set('downPort', 3001); + scfg.set('rightPort', 3001); const server1 = new Server(); // up server scfg.set('port', 3001); - scfg.set('upPort', 3000); - scfg.set('downPort', 1001); + scfg.set('leftPort', 3000); + scfg.set('rightPort', 1001); const server2 = new Server(); // down server cfg.set('worldWidth', 10); cfg.set('worldHeight', 10); @@ -644,7 +648,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() } else if (man2.organisms.size === 2) { destroy(); } @@ -695,11 +699,11 @@ describe("client/src/manager/Manager", () => { scfg.set('modeDistributed', true); scfg.set('maxConnections', 1); scfg.set('port', 3000); - scfg.set('downPort', 3001); + scfg.set('rightPort', 3001); const server1 = new Server(); // up server scfg.set('port', 3001); - scfg.set('upPort', 3000); - scfg.set('downPort', 1001); + scfg.set('leftPort', 3000); + scfg.set('rightPort', 1001); const server2 = new Server(); // down server cfg.set('worldWidth', 10); cfg.set('worldHeight', 10); @@ -717,13 +721,13 @@ describe("client/src/manager/Manager", () => { ocfg.set('orgClonePeriod', 0); ocfg.set('orgStartEnergy', 10000); cfg.set('worldCyclical', false); - World.prototype.getFreePos = () => {return {x: 1, y: 0}}; + World.prototype.getFreePos = () => {return {x: 0, y: 1}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); man2.on(EVENTS.STEP_IN, () => stepInFlag = true); @@ -754,17 +758,15 @@ describe("client/src/manager/Manager", () => { let stepInBack = false; const destroy = () => { man1.destroy(() => { - //man2.destroy(() => { - waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { - World.prototype.getFreePos = freePos; - ocfg.reset(); - scfg.reset(); - cfg.reset(); - done(); - }); + waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { + World.prototype.getFreePos = freePos; + ocfg.reset(); + scfg.reset(); + cfg.reset(); + done(); }); - //}); + }); }); }; @@ -776,11 +778,11 @@ describe("client/src/manager/Manager", () => { scfg.set('modeDistributed', true); scfg.set('maxConnections', 1); scfg.set('port', 3000); - scfg.set('downPort', 3001); + scfg.set('rightPort', 3001); const server1 = new Server(); // up server scfg.set('port', 3001); - scfg.set('upPort', 3000); - scfg.set('downPort', 1001); + scfg.set('leftPort', 3000); + scfg.set('rightPort', 1001); const server2 = new Server(); // down server cfg.set('worldWidth', 10); cfg.set('worldHeight', 10); @@ -794,17 +796,17 @@ describe("client/src/manager/Manager", () => { ocfg.set('orgClonePeriod', 0); ocfg.set('orgStartEnergy', 10000); cfg.set('worldCyclical', false); - World.prototype.getFreePos = () => {return {x: 1, y: 5}}; + World.prototype.getFreePos = () => {return {x: 5, y: 1}}; man1.on(EVENTS.ITERATION, () => { if (iterated1 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001100000000000000000000000000); // onStepDown() + org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); } else if (destroyFlag && stepInBack) { stepInBack = false; - expect(man1.organisms.size).toBe(2); + expect(man1.organisms.size).toBe(1); destroy(); } if (iterated1 > 10000) {throw 'Error sending organism between Servers'} @@ -812,9 +814,7 @@ describe("client/src/manager/Manager", () => { }); waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { - waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { - man1.run(); - }); + waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => man1.run()); }); }); }); \ No newline at end of file From 8f45703c9361735ba82f0b1e91ba0d586ccc35b0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 1 Jan 2018 12:49:45 +0200 Subject: [PATCH 083/291] fixed an issue of returning back organism from [Left] server changed servers log a little bit --- client/src/manager/plugins/status/Status.js | 1 + common/src/Helper.js | 2 +- server/src/server/AroundServers.js | 3 +-- server/src/server/Client.js | 6 +++--- server/src/server/Server.js | 2 +- server/src/server/plugins/Api.js | 2 +- server/src/share/Config.js | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index cc7189c..d064fc9 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -65,6 +65,7 @@ class Status extends Configurable { if (!StatusConfig.showMessages) {return} const stamp = Date.now(); this._times++; + console.log(this._manager.activeAround); if (stamp - this._stamp < StatusConfig.period) {return} const man = this._manager; diff --git a/common/src/Helper.js b/common/src/Helper.js index ecb21ff..2b0d339 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -145,7 +145,7 @@ class Helper { const xMap = {0: Config.worldWidth - 1, [Config.worldWidth - 1]: 0}; const yMap = {0: Config.worldHeight - 1, [Config.worldHeight - 1]: 0}; - return [(dir === DIR.LEFT || dir === DIR.RIGHT) && xMap[x] ? xMap[x] : x, (dir === DIR.UP || dir === DIR.DOWN) && yMap[y] ? yMap[y] : y]; + return [(dir === DIR.LEFT || dir === DIR.RIGHT) && typeof(xMap[x]) !== 'undefined' ? xMap[x] : x, (dir === DIR.UP || dir === DIR.DOWN) && typeof(yMap[y]) !== 'undefined' ? yMap[y] : y]; } /** diff --git a/server/src/server/AroundServers.js b/server/src/server/AroundServers.js index 88f4494..6c2e095 100644 --- a/server/src/server/AroundServers.js +++ b/server/src/server/AroundServers.js @@ -142,12 +142,11 @@ class AroundServers extends Observer { _onOpen(client, dir) { client.request(client.socket, TYPES.REQ_SET_NEAR_ACTIVE, FLIP_DIR[dir], (type) => { if (type !== TYPES.RES_SET_NEAR_ACTIVE_OK) { - Console.error(`Unable update active status on '${NAMES[dir]}' server. Response type: ${type}`); + Console.error(`Unable update active status on [${NAMES[dir]}] server. Response type: ${type}`); return; } this._socks[dir] = client.socket; this.fire(OPEN, dir); - Console.info(`Active status of '${NAMES[dir]}' server has updated`); }); } diff --git a/server/src/server/Client.js b/server/src/server/Client.js index a90705b..c4dff28 100644 --- a/server/src/server/Client.js +++ b/server/src/server/Client.js @@ -43,7 +43,7 @@ class Client extends BaseClient { */ onError(event) { super.onError(event); - Console.warn(`'${NAMES[this._dir]}' server error: ${event.message} on ${this.host}:${this.port}`); + Console.warn(`[${NAMES[this._dir]}] server error: ${event.message} on ${this.host}:${this.port}`); } /** @@ -70,7 +70,7 @@ class Client extends BaseClient { // // We have to show message only if we had been active for some time // - active && Console.warn(`'${NAMES[this._dir]}' server has disconnected by reason: '${this.closeReason}' on ${this.host}:${this.port}`); + active && Console.warn(`[${NAMES[this._dir]}] server has disconnected by reason: '${this.closeReason}' on ${this.host}:${this.port}`); } /** @@ -80,7 +80,7 @@ class Client extends BaseClient { */ onOpen(event) { super.onOpen(event); - Console.info(`'${NAMES[this._dir]}' server has connected on ${this.host}:${this.port}`); + Console.info(`[${NAMES[this._dir]}] server has connected on ${this.host}:${this.port}`); } } diff --git a/server/src/server/Server.js b/server/src/server/Server.js index dfee317..ed5fb79 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -234,7 +234,7 @@ class Server extends Connection { sock.removeAllListeners('error'); sock.removeAllListeners('close'); servers && servers.setSocket(sock, dir); - clientId !== false && Console.warn(`Client '${isServer ? NAMES[dir] : clientId}' has disconnected by reason: ${this.closeReason}`); + clientId !== false && Console.warn(`Client [${isServer ? NAMES[dir] : clientId}] has disconnected by reason: ${this.closeReason}`); } } diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 5504f40..da965ea 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -129,7 +129,7 @@ class Api extends BaseApi { this.parent.aroundServers.setSocket(this.sock, dir); this.parent.response(this.sock, TYPES.RES_SET_NEAR_ACTIVE_OK, reqId); this._onServerOpen(dir); - Console.info(`'${NAMES[dir]}' server has connected`); + Console.info(`[${NAMES[dir]}] server has connected`); } /** diff --git a/server/src/share/Config.js b/server/src/share/Config.js index 9ed76ee..4424cc8 100644 --- a/server/src/share/Config.js +++ b/server/src/share/Config.js @@ -58,7 +58,7 @@ ServerConfig.init({ /** * {Number} Port number of server on the right */ - rightPort: 8101, + rightPort: 8302, /** * {String} Host address of server below. Shouldn't contain port */ @@ -66,7 +66,7 @@ ServerConfig.init({ /** * {Number} Port number of server below */ - downPort: 8102, + downPort: 8202, /** * {String} Host address of server on the left. Shouldn't contain port */ @@ -74,7 +74,7 @@ ServerConfig.init({ /** * {Number} Port number of server on the left */ - leftPort: 8103 + leftPort: 8203 }); module.exports = {Config: ServerConfig.cfg(), api: ServerConfig}; \ No newline at end of file From 77a41fc63a43b501dded5102be530759df4c0e01 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 1 Jan 2018 14:36:29 +0200 Subject: [PATCH 084/291] removed extra console.log() --- client/src/manager/plugins/status/Status.js | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index d064fc9..cc7189c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -65,7 +65,6 @@ class Status extends Configurable { if (!StatusConfig.showMessages) {return} const stamp = Date.now(); this._times++; - console.log(this._manager.activeAround); if (stamp - this._stamp < StatusConfig.period) {return} const man = this._manager; From 5f15841954f0ec19771182a9c7302a013703530a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 1 Jan 2018 16:12:11 +0200 Subject: [PATCH 085/291] added test for three clients and one server #83 --- client/src/manager/ManagerSpec.js | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 5434b4b..d49416c 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -817,4 +817,54 @@ describe("client/src/manager/Manager", () => { waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => man1.run()); }); }); + + it("Checking moving of organism through three Managers", (done) => { + const ocfg = new ConfigHelper(OConfig); + const cfg = new ConfigHelper(Config); + const server = new Server(); + cfg.set('worldWidth', 10); + cfg.set('worldHeight', 10); + const man1 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man2 = new Manager(false); + delete Config.organisms; + delete Config.status; + const man3 = new Manager(false); + let iterated1 = 0; + let iterated2 = 0; + let freePos = World.prototype.getFreePos; + let org1 = null; + let waitObj = {done: false}; + let i = 0; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + man3.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + World.prototype.getFreePos = freePos; + ocfg.reset(); + cfg.reset(); + done(); + }); + }); + }); + }); + }; + + ocfg.set('orgStartAmount', 1); + ocfg.set('orgRainMutationPeriod', 0); + ocfg.set('orgCloneMutationPercent', 0); + ocfg.set('orgEnergySpendPeriod', 0); + ocfg.set('orgClonePeriod', 0); + ocfg.set('orgStartEnergy', 10000); + World.prototype.getFreePos = () => {return {x: 5, y: ++i === 1 ? 1 : 2}}; + + testQ(done, + [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], + [waitObj], + [man1, EVENTS.ITERATION, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001010000000000000000000000000)], // onStepRight() + [man3, EVENTS.STEP_IN, () => {}, () => destroy()] + ); + }); }); \ No newline at end of file From 6d10cec1cb77b3c911287655b1a9bd949b56b61e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 1 Jan 2018 16:15:35 +0200 Subject: [PATCH 086/291] small fix of test #83 --- client/src/manager/ManagerSpec.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index d49416c..4ee760e 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -831,10 +831,7 @@ describe("client/src/manager/Manager", () => { delete Config.organisms; delete Config.status; const man3 = new Manager(false); - let iterated1 = 0; - let iterated2 = 0; let freePos = World.prototype.getFreePos; - let org1 = null; let waitObj = {done: false}; let i = 0; const destroy = () => { From 1f5a7816f607b3d2ee05ed8fa4faa44b756a09b5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 2 Jan 2018 19:49:38 +0200 Subject: [PATCH 087/291] Manager speed optimizations Global classes refactoring Fixed an issue of killing all the population Fixed an issue on 'null' in up left corner (Status clientId) Added LOOP global event Fixed an issue of reset current code line after copy mutation Optimized Observer.destroy() --- client/src/manager/Manager.js | 25 +++-- .../src/manager/plugins/organisms/Config.js | 36 +++---- .../src/manager/plugins/organisms/Mutator.js | 3 +- .../src/manager/plugins/organisms/Organism.js | 24 +++-- .../manager/plugins/organisms/Organisms.js | 102 +++++++++--------- .../plugins/organisms/dos/Organisms.js | 17 ++- client/src/manager/plugins/status/Status.js | 2 +- client/src/share/Config.js | 6 +- client/src/share/Events.js | 41 +++---- client/src/view/Canvas.js | 2 +- client/src/vm/VM.js | 14 ++- common/src/Observer.js | 2 +- 12 files changed, 146 insertions(+), 128 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 5d6e7a3..78ea87c 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -23,6 +23,10 @@ const Console = require('./../share/Console'); const World = require('./../view/World').World; const WEVENTS = require('./../view/World').EVENTS; const Canvas = require('./../view/Canvas'); +/** + * {Function} Shortcut to the datetime stamp getter + */ +const TIMER = Date.now; class Manager extends Observer { /** @@ -142,6 +146,15 @@ class Manager extends Observer { this.fire(EVENTS.ITERATION); } + /** + * Is called after all iterations + * @param {Number} counter Global counter as an analog of time + * @param {Number} stamp UNIX time stamp + */ + onLoop(counter, stamp) { + this.fire(EVENTS.LOOP); + } + /** * Returns true if at least one other Manager/client is around and is connected * to the current @@ -238,14 +251,14 @@ class Manager extends Observer { // prevent flickering of organisms in a canvas. It makes their // movement smooth // - const amount = this._visualized ? 1 : OConfig.codeIterationsPerOnce; - const timer = Date.now; - let counter = this._counter; + let amount = this._visualized ? 1 : OConfig.codeIterationsPerOnce; + let counter = this._counter; + let i; - for (let i = 0; i < amount; i++) { - this.onIteration(counter++, timer()); + for (i = counter, amount = counter + amount; i < amount; i++) { + this.onIteration(i, TIMER()); } - this._counter = counter; + this.onLoop(this._counter = i, TIMER()); this._active && this.zeroTimeout(this._onLoopCb); } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index de0c84a..0baf0fa 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -18,6 +18,11 @@ const Config = { * {Number} Maximum color index of organism */ ORG_MAX_COLOR: Number.MAX_SAFE_INTEGER, + /** + * {Number} Max value, which we may use in orgMutationProbs array. We may use + * range: [0...ORG_MUTATION_PROBS_MAX_VAL] including these values + */ + ORG_MUTATION_PROBS_MAX_VAL: 100, /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of @@ -41,46 +46,41 @@ const Config = { * ] */ orgMutationProbs: [10,1,1,100,1,1,1,1,1,1], - /** - * {Number} Max value, which we may use in orgMutationProbs array. We may use - * range: [0...orgMutationProbsMaxValue] including these values - */ - orgMutationProbsMaxValue: 100, /** * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ - orgCloneMutationPercent: 0.000, + orgCloneMutationPercent: 0.01, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 10, + orgClonePeriod: 300, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 1000, + orgCrossoverPeriod: 0, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 1000, + orgRainMutationPeriod: 300, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.01, + orgRainMutationPercent: 0.5, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 100, + orgStartAmount: 300, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 1000000, + orgStartEnergy: 500000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB @@ -108,11 +108,11 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 20, + orgGarbagePeriod: 10, /** * {Number} Size of organism stack (internal memory) */ - orgMemSize: 1024, + orgMemSize: 128, /** * {Number} Percent of energy, which will be given to the child */ @@ -127,7 +127,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 300, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -135,7 +135,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 150, + codeMaxSize: 100, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. @@ -152,7 +152,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 5, + codeYieldPeriod: 2, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 100, + codeIterationsPerOnce: 10, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 4483164..5cbc963 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -67,7 +67,6 @@ class Mutator { static _onCopy(org) { org.changes += (org.vm.copyLines() * MAX_BITS); - } static _onPeriod(org) { @@ -81,7 +80,7 @@ class Mutator { } static _onProbs(org) { - org.mutationProbs[Helper.rand(org.mutationProbs.length)] = Helper.rand(OConfig.orgMutationProbsMaxValue) || 1; + org.mutationProbs[Helper.rand(org.mutationProbs.length)] = Helper.rand(OConfig.ORG_MUTATION_PROBS_MAX_VAL) || 1; org.changes++; } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index e1eb4ad..db7c260 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -55,7 +55,7 @@ class Organism extends Observer { this._id = id; this._x = x; this._y = y; - this._changes = 1; + this._iterations = 0; this._alive = alive; this._item = item; this._fnId = 0; @@ -106,7 +106,7 @@ class Organism extends Observer { * @return {String} JSON string */ serialize() { - let json = { + let json = { id : this._id, x : this._x, y : this._y, @@ -164,18 +164,20 @@ class Organism extends Observer { } fitness() { - return Math.abs(OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; + return /*Math.abs(OConfig.codeMaxSize - this.vm.size) * */ this._energy * this._changes; } destroy() { this.fire(EVENTS.DESTROY, this); - this._alive = false; - this._energy = 0; - this._item = null; - this._mem = null; + this._alive = false; + this._energy = 0; + this._item = null; + this._mem = null; + this._mutationProbs = null; this.vm && this.vm.destroy(); - this.vm = null; - this._codeEndCb = null; + this.vm = null; + this._codeEndCb = null; + this._operatorCls = null; super.destroy(); } @@ -195,7 +197,7 @@ class Organism extends Observer { this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; - this._iterations = 0; + this._changes = 1; this._mem = []; } @@ -208,7 +210,7 @@ class Organism extends Observer { this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; this._cloneEnergyPercent = parent.cloneEnergyPercent; - this._iterations = parent.iterations; + this._changes = parent.changes; this._mem = parent.mem.slice(); } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index d500a37..8123e69 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -16,9 +16,8 @@ const EVENTS = require('./../../../../src/share/Events').EVENTS; const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); -const RAND_OFFS = 4; +const RAND_OFFS = 3; const MAX_BITS = Num.MAX_BITS; - // TODO: inherit this class from Configurable class Organisms extends Configurable { /** @@ -58,13 +57,6 @@ class Organisms extends Configurable { */ onClone(org, child) {} - /** - * Is called after organism has created - * @param {Organism} org - * @abstract - */ - onAfterCreateOrg(org) {} - /** * Is called after organism has killed * @param {Organism} org Killed organism @@ -87,10 +79,12 @@ class Organisms extends Configurable { this.manager = manager; this.randOrgItem = this.organisms.first; this._mutator = new Mutator(manager); - this._onIterationCb = this.onIteration.bind(this); + this._onIterationCb = this._onIteration.bind(this); + this._onLoopCb = this._onLoop.bind(this); this.reset(); Helper.override(manager, 'onIteration', this._onIterationCb); + Helper.override(manager, 'onLoop', this._onLoopCb); } destroy() { @@ -99,35 +93,16 @@ class Organisms extends Configurable { while (item && (org = item.val)) {org.destroy(); item = item.next} Helper.unoverride(this.manager, 'onIteration', this._onIterationCb); + Helper.unoverride(this.manager, 'onLoop', this._onLoopCb); this._mutator.destroy(); this._mutator = null; this.manager = null; this._onIterationCb = null; + this._onLoopCb = null; super.destroy(); } - /** - * Override of Manager.onIteration() method. Is called on every - * iteration of main loop. The counter is an analog of time. - * @param {Number} counter Value of main loop counter. - * @param {Number} stamp Time stamp of current iteration - */ - onIteration(counter, stamp) { - let item = this.organisms.first; - let org; - - while (item && (org = item.val)) { - org.run(); - this.onOrganism(org); - item = item.next; - } - - this.updateClone(counter); - this.updateCrossover(counter); - this.updateCreate(); - } - /** * Is called every time after organism's code was run * @param {Organism} org @@ -150,9 +125,9 @@ class Organisms extends Configurable { const needClone = counter % OConfig.orgClonePeriod === 0 && OConfig.orgClonePeriod !== 0; let orgAmount = orgs.size; if (!needClone || orgAmount < 1) {return false} - let org1 = this.getRandOrg(); - let org2 = this.getRandOrg(); - if (!org1.alive && !org2.alive) {return false} + let org1 = this._randOrg(); + let org2 = this._randOrg(); + if (!org1.alive && !org2.alive || org1 === org2) {return false} let tmpOrg = this._tournament(org1, org2); if (tmpOrg === org2) {[org1, org2] = [org2, org1]} @@ -187,19 +162,6 @@ class Organisms extends Configurable { } } - getRandOrg() { - const offs = Helper.rand(RAND_OFFS); - let item = this.randOrgItem; - - for (let i = 0; i < offs; i++) { - if ((item = item.next) === null) { - item = this.organisms.first; - } - } - - return (this.randOrgItem = item).val; - } - reset() { this._orgId = 0; } @@ -225,17 +187,53 @@ class Organisms extends Configurable { last.val = org; this.addOrgHandlers(org); - this.move(pos.x, pos.y, pos.x, pos.y, org); - this.onAfterCreateOrg(org); + this.move(-1, -1, pos.x, pos.y, org); this.manager.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); return true; } + /** + * Override of Manager.onIteration() method. Is called on every + * iteration of main loop. The counter is an analog of time. + * @param {Number} counter Value of main loop counter. + * @param {Number} stamp Time stamp of current iteration + */ + _onIteration(counter, stamp) { + let item = this.organisms.first; + let org; + + while (item && (org = item.val)) { + org.run(); + this.onOrganism(org); + item = item.next; + } + + this.updateClone(counter); + this.updateCrossover(counter); + } + + _onLoop() { + this.updateCreate(); + } + + _randOrg() { + const offs = Helper.rand(RAND_OFFS) + 1; + let item = this.randOrgItem; + + for (let i = 0; i < offs; i++) { + if ((item = item.next) === null) { + item = this.organisms.first; + } + } + + return (this.randOrgItem = item).val; + } + _tournament(org1 = null, org2 = null) { - org1 = org1 || this.getRandOrg(); - org2 = org2 || this.getRandOrg(); + org1 = org1 || this._randOrg(); + org2 = org2 || this._randOrg(); if (!org1.alive && !org2.alive) {return false} if ((org2.alive && !org1.alive) || this.compare(org2, org1)) { @@ -272,7 +270,7 @@ class Organisms extends Configurable { const world = this.manager.world; this.reset(); - for (let i = 0; i < OConfig.orgStartAmount; i++) { + for (let i = 0, len = OConfig.orgStartAmount; i < len; i++) { this.createOrg(world.getFreePos()); } Console.info('Population has created'); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index c634be2..6ce6f22 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -64,6 +64,14 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { let energy = (((org.energy * org.cloneEnergyPercent) + 0.5) << 1) >>> 1; // analog of Math.round() + // + // This is very special case, when organisms cheating by creating + // ancestors and put all energy into them at the same time resetting + // their iterations property and make them immortal + // + if (energy === org.energy) { + energy--; + } org.grabEnergy(energy); child.grabEnergy(child.energy - energy); } @@ -86,15 +94,6 @@ class Organisms extends BaseOrganisms { return new Organism(...args); } - /** - * Is called after organism has created - * @param {Organism} org - * @override - */ - onAfterCreateOrg(org) { - this.manager.positions[org.posId] = org; - } - /** * Is called after organism has killed * @param {Organism} org Killed organism diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index cc7189c..dab7d0a 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -81,7 +81,7 @@ class Status extends Configurable { const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - man.hasView && man.canvas.text(5, 20, sips + man.clientId); + man.hasView && man.canvas.text(5, 20, sips + (man.clientId && man.clientId || '')); this._onAfterLog(stamp); } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 8043ec7..c6dc8c9 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -44,11 +44,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920, + worldWidth: 400, /** * {Number} World height */ - worldHeight: 1010, + worldHeight: 400, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 2c44dfb..c84e074 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -6,26 +6,27 @@ * TODO: find unused and remove. But after main code is done. */ const EVENTS = { - ITERATION : 0, - IPS : 1, - BACKUP : 2, - ORGANISM : 3, - GRAB_ENERGY : 4, - UPDATE_ENERGY : 5, - KILL_ORGANISM : 6, - MUTATIONS : 7, - CLONE : 8, - EAT : 9, - STEP : 10, - STEP_OUT : 11, - STEP_IN : 12, - BORN_ORGANISM : 13, - GET_ENERGY : 14, - DESTROY : 15, - RUN : 16, - STOP : 17, - RESET_CODE : 18, - CHECK_AT : 19 + ITERATION : 0, + LOOP : 1, + IPS : 2, + BACKUP : 3, + ORGANISM : 4, + GRAB_ENERGY : 5, + UPDATE_ENERGY : 6, + KILL_ORGANISM : 7, + MUTATIONS : 8, + CLONE : 9, + EAT : 10, + STEP : 11, + STEP_OUT : 12, + STEP_IN : 13, + BORN_ORGANISM : 14, + GET_ENERGY : 15, + DESTROY : 16, + RUN : 17, + STOP : 18, + RESET_CODE : 19, + CHECK_AT : 20 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index c1d946f..30d6b33 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -23,7 +23,7 @@ class Canvas { this._animate = this._onAnimate.bind(this); this._visualize = true; - this._ctx.font = "18px Consolas"; + this._ctx.font = "18px Consolas"; this._ctx.fillStyle = "white"; this.clear(); window.requestAnimationFrame(this._animate); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index b81db7e..d408d5b 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -131,10 +131,14 @@ class VM extends Observer { destroy() { this._operators.destroy && this._operators.destroy(); - this._operators = null; - this._vars = null; - this._code = null; - this._onCodeEnd = null; + this._operators = null; + this._operatorCls = null; + this._offsets = null; + this._vars = null; + this._code = null; + this._onCodeEnd = null; + this._obs = null; + this._ops = null; super.destroy(); } @@ -208,10 +212,12 @@ class VM extends Observer { // if (rand(2) === 0) { code.splice(rand(start), 0, ...code.slice(start, end)); + this._reset(); return end - start; } code.splice(end + rand(codeLen - end + 1), 0, ...code.slice(start, end)); + this._reset(); return end - start; } diff --git a/common/src/Observer.js b/common/src/Observer.js index 37fe435..2d68309 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -63,7 +63,7 @@ class Observer { } destroy() { - this.clear(); + this._handlers = null; } _resetEvents() { From 9929666926cbc5948c3cff85744ea0600d527582 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 3 Jan 2018 00:34:59 +0200 Subject: [PATCH 088/291] fixed issue with error on console related to Observer.destroy() Fixed changes inheritance mechanism #103 --- .../src/manager/plugins/organisms/Config.js | 24 +++++++++---------- .../src/manager/plugins/organisms/Organism.js | 4 ++-- .../plugins/organisms/dos/Organisms.js | 8 +++++-- client/src/manager/plugins/status/Status.js | 2 +- client/src/share/Config.js | 8 +++---- common/src/Observer.js | 2 +- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 0baf0fa..737c715 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -50,22 +50,22 @@ const Config = { * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ - orgCloneMutationPercent: 0.01, + orgCloneMutationPercent: 0.0, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 300, + orgClonePeriod: 30, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 3000, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 300, + orgRainMutationPeriod: 3000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -80,7 +80,7 @@ const Config = { * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 500000, + orgStartEnergy: 100000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB @@ -95,7 +95,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 0, + orgAlivePeriod: 100000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -108,7 +108,7 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 10, + orgGarbagePeriod: 8, /** * {Number} Size of organism stack (internal memory) */ @@ -121,13 +121,13 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.0, + orgStepEnergySpendPercent: 0.1, /** * {Number} Maximum amount of organisms in a world. If some organism will * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 100, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -135,7 +135,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 100, + codeMaxSize: 64, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. @@ -152,7 +152,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 2, + codeYieldPeriod: 5, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. @@ -167,7 +167,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 10, + codeIterationsPerOnce: 200, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index db7c260..f8a8cd8 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -10,7 +10,7 @@ const Helper = require('./../../../../../common/src/Helper'); const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENTS = require('./../../../share/Events').EVENTS; const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; -const VM = require('./../../../vm/VM'); +const VM = require('./../../../vm/VM'); const IS_NUM = Helper.isNumeric; @@ -164,7 +164,7 @@ class Organism extends Observer { } fitness() { - return /*Math.abs(OConfig.codeMaxSize - this.vm.size) * */ this._energy * this._changes; + return Math.abs(OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; } destroy() { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 6ce6f22..f94febd 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -63,16 +63,20 @@ class Organisms extends BaseOrganisms { * @override */ onClone(org, child) { - let energy = (((org.energy * org.cloneEnergyPercent) + 0.5) << 1) >>> 1; // analog of Math.round() + const percent = org.cloneEnergyPercent; + const changes = (((org.changes * percent) + 0.5) << 1) >>> 1; // analog of Math.round() + let energy = (((org.energy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() // - // This is very special case, when organisms cheating by creating + // This is very special/rare case, when organisms cheating by creating // ancestors and put all energy into them at the same time resetting // their iterations property and make them immortal // if (energy === org.energy) { energy--; } + org.changes -= changes; org.grabEnergy(energy); + child.changes -= child.changes - changes; child.grabEnergy(child.energy - energy); } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index dab7d0a..f12c708 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -77,7 +77,7 @@ class Status extends Configurable { const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); const sfit = format(this._fitness, 'fit', orgAmount, 3, 14 ); - const schanges = format(this._changes, 'che', orgAmount, 3, 12, 1, true); + const schanges = format(this._changes, 'che', orgAmount, 3, 14, 1, true); const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index c6dc8c9..8acbe56 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -44,11 +44,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 400, + worldWidth: 1920, /** * {Number} World height */ - worldHeight: 400, + worldHeight: 1010, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -75,7 +75,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.1, + worldEnergyCheckPercent: 0.2, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if diff --git a/common/src/Observer.js b/common/src/Observer.js index 2d68309..36d378b 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -63,7 +63,7 @@ class Observer { } destroy() { - this._handlers = null; + this._handlers = {}; } _resetEvents() { From 0d336dd24ff6a6712253fe80ca12a5b8410d449c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 3 Jan 2018 00:39:49 +0200 Subject: [PATCH 089/291] temporary fix for #103 --- client/src/manager/plugins/organisms/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 737c715..b218bf2 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -95,7 +95,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 100000, + orgAlivePeriod: 0, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two From 0f4a416592a28eabf6eb15003990c60b1bbcf5d7 Mon Sep 17 00:00:00 2001 From: tmptrash Date: Thu, 4 Jan 2018 19:15:37 +0200 Subject: [PATCH 090/291] refactoring --- client/src/manager/plugins/organisms/Mutator.js | 6 ++++++ client/src/manager/plugins/organisms/Organism.js | 12 +++++------- client/src/manager/plugins/organisms/Organisms.js | 6 +++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 5cbc963..9459c82 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -123,6 +123,12 @@ class Mutator { if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0) {this._mutate(child)} } + /** + * IMPORTANT: mutations should be applied only after last line of organism's code + * has interpreted + * @param {Organism} org Current organism + * @param {Boolean} clone true if mutation is applying after clone + */ _mutate(org, clone = true) { const vm = org.vm; const probIndex = Helper.probIndex; diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index f8a8cd8..5ce88fa 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -91,7 +91,8 @@ class Organism extends Observer { } /** - * Runs one code iteration and returns + * Runs one code iteration (amount of lines set in Config.codeYieldPeriod) and returns + * organism destroy state * @return {Boolean} false means that organism was destroyed */ run() { @@ -159,6 +160,7 @@ class Organism extends Observer { grabEnergy(amount) { if (!IS_NUM(amount)) {return true} const noEnergy = (this._energy -= amount) < 1; + this.fire(EVENTS.GRAB_ENERGY, amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); return !noEnergy; } @@ -234,14 +236,10 @@ class Organism extends Observer { */ _updateEnergy() { if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - const codeSize = this.vm.size; - let grabSize = Math.floor(codeSize / OConfig.orgGarbagePeriod); - + let grabSize = Math.floor(this.vm.size / OConfig.orgGarbagePeriod); if (grabSize < 1) {grabSize = 1} - grabSize = Math.min(this._energy, grabSize); - this.fire(EVENTS.GRAB_ENERGY, grabSize); - return this.grabEnergy(grabSize); + return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 8123e69..1901299 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -204,7 +204,7 @@ class Organisms extends Configurable { let item = this.organisms.first; let org; - while (item && (org = item.val)) { + while (org = item && item.val) { org.run(); this.onOrganism(org); item = item.next; @@ -245,9 +245,9 @@ class Organisms extends Configurable { _clone(org) { if (this.onBeforeClone(org) === false) {return false} - let pos = this.manager.world.getNearFreePos(org.x, org.y); + let pos = this.manager.world.getNearFreePos(org.x, org.y); if (pos === false || this.createOrg(pos, org) === false) {return false} - let child = this.organisms.last.val; + let child = this.organisms.last.val; this.onClone(org, child); this.manager.fire(EVENTS.CLONE, org, child); From 055b0703aa53fb658344fdcf915c429ee65880db Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 5 Jan 2018 12:39:59 +0200 Subject: [PATCH 091/291] updated main mechanism of calculating fitness of organisms --- client/src/manager/Manager.js | 3 --- client/src/manager/ManagerSpec.js | 2 +- .../src/manager/plugins/organisms/Config.js | 10 ++++---- .../src/manager/plugins/organisms/Organism.js | 15 +++++------ .../manager/plugins/organisms/Organisms.js | 21 +++++++--------- .../plugins/organisms/dos/Organisms.js | 3 --- client/src/manager/plugins/status/Config.js | 2 +- client/src/manager/plugins/status/Status.js | 25 ++++++++++--------- client/src/share/Config.js | 8 +++--- 9 files changed, 41 insertions(+), 48 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 78ea87c..663fac8 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -102,9 +102,6 @@ class Manager extends Observer { get activeAround() {return this._activeAround} get active() {return this._active} get codeRuns() {return this._codeRuns} - // TODO: this getter will be removed when hasView will be - // TODO: removed from Status plugin - get hasView() {return this._hasView} set codeRuns(cr) {this._codeRuns = cr} set clientId(id) {this._clientId = id} diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 4ee760e..91c23aa 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -99,7 +99,7 @@ describe("client/src/manager/Manager", () => { expect(man.active).toBe(false); expect(man.clientId).toBe(null); expect(man.isDistributed()).toBe(false); - expect(man.hasView).toBe(false); + expect(man.canvas).toBe(null); man.destroy(done); }); it("Checking creation of two managers", (done) => { diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index b218bf2..6fab5ca 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -70,7 +70,7 @@ const Config = { * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.5, + orgRainMutationPercent: 0.2, /** * {Number} Amount of organisms we have to create on program start */ @@ -90,12 +90,12 @@ const Config = { * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. */ - orgEnergySpendPeriod: 50, + orgEnergySpendPeriod: 20, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 0, + orgAlivePeriod: 20000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -108,7 +108,7 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 8, + orgGarbagePeriod: 5, /** * {Number} Size of organism stack (internal memory) */ @@ -127,7 +127,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 100, + orgMaxOrgs: 300, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index f8a8cd8..90708d0 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -38,15 +38,15 @@ class Organism extends Observer { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Function} codeEndCb Callback, which is called at the + * @param {Function} onCodeEnd Callback, which is called at the * end of every code iteration. * @param {Function} operatorCls Class of operators * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, codeEndCb, operatorCls, parent = null) { + constructor(id, x, y, alive, item, onCodeEnd, operatorCls, parent = null) { super(EVENT_AMOUNT); - this._codeEndCb = codeEndCb; + this._onCodeEnd = onCodeEnd; this._operatorCls = operatorCls; if (parent === null) {this._create()} @@ -98,6 +98,7 @@ class Organism extends Observer { this._iterations++; if (this.onBeforeRun() === false) {return true} this.onRun(); + this.alive && this.vm.size === 0 && this._onCodeEnd(this, 0); return this.alive && this._updateDestroy() && this._updateEnergy(); } @@ -164,7 +165,7 @@ class Organism extends Observer { } fitness() { - return Math.abs(OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; + return (OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; } destroy() { @@ -176,7 +177,7 @@ class Organism extends Observer { this._mutationProbs = null; this.vm && this.vm.destroy(); this.vm = null; - this._codeEndCb = null; + this._onCodeEnd = null; this._operatorCls = null; super.destroy(); @@ -189,7 +190,7 @@ class Organism extends Observer { } _create() { - this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls); + this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._color = OConfig.orgStartColor; this._mutationProbs = OConfig.orgMutationProbs.slice(); @@ -202,7 +203,7 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this._codeEndCb.bind(this, this), this, this._operatorCls, parent.vm); + this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls, parent.vm); this._energy = parent.energy; this._color = parent.color; this._mutationProbs = parent.mutationProbs.slice(); diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 8123e69..316e976 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -73,6 +73,13 @@ class Organisms extends Configurable { */ createEmptyOrg(...args) {} + /** + * Is called at the end of run() method + * @param {Organism} org Current organism + * @abstract + */ + onOrganism(org) {} + constructor(manager) { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; @@ -103,14 +110,6 @@ class Organisms extends Configurable { super.destroy(); } - /** - * Is called every time after organism's code was run - * @param {Organism} org - */ - onOrganism(org) { - org.alive && org.vm.size === 0 && this._onCodeEnd(org, 0); - } - addOrgHandlers(org) { org.on(EVENTS.DESTROY, this._onKillOrg.bind(this)); } @@ -121,9 +120,8 @@ class Organisms extends Configurable { * @returns {boolean} */ updateClone(counter) { - const orgs = this.organisms; const needClone = counter % OConfig.orgClonePeriod === 0 && OConfig.orgClonePeriod !== 0; - let orgAmount = orgs.size; + let orgAmount = this.organisms.size; if (!needClone || orgAmount < 1) {return false} let org1 = this._randOrg(); let org2 = this._randOrg(); @@ -139,8 +137,7 @@ class Organisms extends Configurable { } updateCrossover(counter) { - const orgs = this.organisms; - const orgAmount = orgs.size; + const orgAmount = this.organisms.size; const needCrossover = counter % OConfig.orgCrossoverPeriod === 0 && OConfig.orgCrossoverPeriod !== 0; if (!needCrossover || orgAmount < 1) {return false} diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index f94febd..336f6b7 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -64,7 +64,6 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { const percent = org.cloneEnergyPercent; - const changes = (((org.changes * percent) + 0.5) << 1) >>> 1; // analog of Math.round() let energy = (((org.energy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() // // This is very special/rare case, when organisms cheating by creating @@ -74,9 +73,7 @@ class Organisms extends BaseOrganisms { if (energy === org.energy) { energy--; } - org.changes -= changes; org.grabEnergy(energy); - child.changes -= child.changes - changes; child.grabEnergy(child.energy - energy); } diff --git a/client/src/manager/plugins/status/Config.js b/client/src/manager/plugins/status/Config.js index e8bb97c..e64416d 100644 --- a/client/src/manager/plugins/status/Config.js +++ b/client/src/manager/plugins/status/Config.js @@ -11,7 +11,7 @@ const Config = { /** * {Number} Delay in milliseconds between showing one status line */ - period: 10000 + period: 2000 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index f12c708..126ece3 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -43,7 +43,7 @@ class Status extends Configurable { this._codeSize = 0; this._runLines = 1; this._times = 0; - this._oldValues = [0, 0]; + this._oldValues = [0, 0, 0]; this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); @@ -72,16 +72,16 @@ class Status extends Configurable { const format = Status._format; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); - const sfit = format(this._fitness, 'fit', orgAmount, 3, 14 ); - const schanges = format(this._changes, 'che', orgAmount, 3, 14, 1, true); - const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); + const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); + const schanges = format(this._changes, 'che', orgAmount, 2, 14, 10000000, true); + const sfit = format(this._fitness, 'fit', orgAmount, 2, 14 ); + const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - man.hasView && man.canvas.text(5, 20, sips + (man.clientId && man.clientId || '')); + man.canvas && man.canvas.text(5, 20, sips + (man.clientId && man.clientId || '')); this._onAfterLog(stamp); } @@ -110,13 +110,14 @@ class Status extends Configurable { } energy /= size; + changes /= size; fitness /= size; this._curEnergy = energy; this._energy = (energy - olds[0]) / lines; - this._fitness = (fitness - olds[1]) / lines; - this._changes = changes; + this._changes = (changes - olds[1]) / lines; + this._fitness = (fitness - olds[2]) / lines; this._codeSize = codeSize; - this._oldValues = [energy, fitness]; + this._oldValues = [energy, changes, fitness]; } _onAfterLog(stamp) { diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 8acbe56..9c78e7c 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -48,7 +48,7 @@ ClientConfig.init({ /** * {Number} World height */ - worldHeight: 1010, + worldHeight: 1080, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -75,13 +75,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.2, + worldEnergyCheckPercent: 0.5, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 10000, + worldEnergyCheckPeriod: 8000, /** * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages From 75196900aa5c6a92be13bac7354bd4d484eb906f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 5 Jan 2018 23:08:26 +0200 Subject: [PATCH 092/291] refactoring changed very core logic of cloning and crossover. from now looser organism are not killed by the system after clone/crossover --- .../src/manager/plugins/organisms/Config.js | 3 +- .../src/manager/plugins/organisms/Organism.js | 7 +- .../manager/plugins/organisms/Organisms.js | 90 +++++++++---------- .../plugins/organisms/dos/Organisms.js | 33 +++---- client/src/share/Config.js | 10 +-- 5 files changed, 71 insertions(+), 72 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 6fab5ca..c1bd374 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -114,7 +114,8 @@ const Config = { */ orgMemSize: 128, /** - * {Number} Percent of energy, which will be given to the child + * {Number} Percent of energy, which will be given to the child. Set to 0.0 + * to share the same amount of energy with child (energy duplication) */ orgCloneEnergyPercent: 0.5, /** diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 544dec2..bfab474 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -186,9 +186,10 @@ class Organism extends Observer { } _updateColor(changes) { - if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { - this._color = OConfig.ORG_FIRST_COLOR; - } + // TODO: tempoorary solution to have red organisms all the time + // if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { + // this._color = OConfig.ORG_FIRST_COLOR; + // } } _create() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index a6e6dc7..2f01d39 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -83,7 +83,6 @@ class Organisms extends Configurable { constructor(manager) { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; - this.manager = manager; this.randOrgItem = this.organisms.first; this._mutator = new Mutator(manager); this._onIterationCb = this._onIteration.bind(this); @@ -99,11 +98,10 @@ class Organisms extends Configurable { let org; while (item && (org = item.val)) {org.destroy(); item = item.next} - Helper.unoverride(this.manager, 'onIteration', this._onIterationCb); - Helper.unoverride(this.manager, 'onLoop', this._onLoopCb); + Helper.unoverride(this.parent, 'onIteration', this._onIterationCb); + Helper.unoverride(this.parent, 'onLoop', this._onLoopCb); this._mutator.destroy(); this._mutator = null; - this.manager = null; this._onIterationCb = null; this._onLoopCb = null; @@ -122,15 +120,13 @@ class Organisms extends Configurable { updateClone(counter) { const needClone = counter % OConfig.orgClonePeriod === 0 && OConfig.orgClonePeriod !== 0; let orgAmount = this.organisms.size; - if (!needClone || orgAmount < 1) {return false} - let org1 = this._randOrg(); - let org2 = this._randOrg(); + if (!needClone || orgAmount >= OConfig.orgMaxOrgs || orgAmount < 1) {return false} + let org1 = this.randOrg(); + let org2 = this.randOrg(); if (!org1.alive && !org2.alive || org1 === org2) {return false} let tmpOrg = this._tournament(org1, org2); if (tmpOrg === org2) {[org1, org2] = [org2, org1]} - - if (orgAmount >= OConfig.orgMaxOrgs) {org2.destroy()} if (org1.alive) {this._clone(org1)} return true; @@ -139,16 +135,13 @@ class Organisms extends Configurable { updateCrossover(counter) { const orgAmount = this.organisms.size; const needCrossover = counter % OConfig.orgCrossoverPeriod === 0 && OConfig.orgCrossoverPeriod !== 0; - if (!needCrossover || orgAmount < 1) {return false} + if (!needCrossover || orgAmount >= OConfig.orgMaxOrgs || orgAmount < 1) {return false} - let org1 = this._tournament(); - let org2 = this._tournament(); - let winner = this._tournament(org1, org2); - let looser = winner === org1 ? org2 : org1; + let org1 = this._tournament(); + let org2 = this._tournament(); - if (looser.alive) { - this._crossover(winner, looser); - } + if (!org1.alive || !org2.alive) {return false} + this._crossover(org1, org2); return true; } @@ -165,7 +158,7 @@ class Organisms extends Configurable { move(x1, y1, x2, y2, org) { let moved = false; - const world = this.manager.world; + const world = this.parent.world; if (world.isFree(x2, y2) === false) {return false} if (x1 !== x2 || y1 !== y2) {moved = true; world.setDot(x1, y1, 0)} @@ -185,12 +178,29 @@ class Organisms extends Configurable { last.val = org; this.addOrgHandlers(org); this.move(-1, -1, pos.x, pos.y, org); - this.manager.fire(EVENTS.BORN_ORGANISM, org); + this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); return true; } + /** + * Returns random organism of current population + * @return {Organism|null} + */ + randOrg() { + const offs = Helper.rand(RAND_OFFS) + 1; + let item = this.randOrgItem; + + for (let i = 0; i < offs; i++) { + if ((item = item.next) === null) { + item = this.organisms.first; + } + } + + return (this.randOrgItem = item).val; + } + /** * Override of Manager.onIteration() method. Is called on every * iteration of main loop. The counter is an analog of time. @@ -215,22 +225,9 @@ class Organisms extends Configurable { this.updateCreate(); } - _randOrg() { - const offs = Helper.rand(RAND_OFFS) + 1; - let item = this.randOrgItem; - - for (let i = 0; i < offs; i++) { - if ((item = item.next) === null) { - item = this.organisms.first; - } - } - - return (this.randOrgItem = item).val; - } - _tournament(org1 = null, org2 = null) { - org1 = org1 || this._randOrg(); - org2 = org2 || this._randOrg(); + org1 = org1 || this.randOrg(); + org2 = org2 || this.randOrg(); if (!org1.alive && !org2.alive) {return false} if ((org2.alive && !org1.alive) || this.compare(org2, org1)) { @@ -242,29 +239,28 @@ class Organisms extends Configurable { _clone(org) { if (this.onBeforeClone(org) === false) {return false} - let pos = this.manager.world.getNearFreePos(org.x, org.y); + let pos = this.parent.world.getNearFreePos(org.x, org.y); if (pos === false || this.createOrg(pos, org) === false) {return false} let child = this.organisms.last.val; this.onClone(org, child); - this.manager.fire(EVENTS.CLONE, org, child); + this.parent.fire(EVENTS.CLONE, org, child); return true; } - _crossover(winner, looser) { - this._clone(winner); + _crossover(org1, org2) { + this._clone(org1); const orgs = this.organisms; let child = orgs.last.val; - if (child.alive && looser.alive) { - child.changes += (child.vm.crossover(looser.vm) * MAX_BITS); - if (orgs.size >= OConfig.orgMaxOrgs) {looser.destroy()} + if (child.alive && org2.alive) { + child.changes += (child.vm.crossover(org2.vm) * MAX_BITS); } } _createPopulation() { - const world = this.manager.world; + const world = this.parent.world; this.reset(); for (let i = 0, len = OConfig.orgStartAmount; i < len; i++) { @@ -274,8 +270,8 @@ class Organisms extends Configurable { } _onCodeEnd(org, lines) { - this.manager.codeRuns++; - this.manager.fire(EVENTS.ORGANISM, org, lines); + this.parent.codeRuns++; + this.parent.fire(EVENTS.ORGANISM, org, lines); } _onKillOrg(org) { @@ -285,9 +281,9 @@ class Organisms extends Configurable { } } this.organisms.del(org.item); - this.manager.world.setDot(org.x, org.y, 0); + this.parent.world.setDot(org.x, org.y, 0); this.onAfterKillOrg(org); - this.manager.fire(EVENTS.KILL_ORGANISM, org); + this.parent.fire(EVENTS.KILL_ORGANISM, org); //Console.info(org.id, ' die'); } @@ -296,7 +292,7 @@ class Organisms extends Configurable { * @return {Number} Amount of organisms within current Manager */ _apiGetAmount() { - return this.manager.organisms.size; + return this.parent.organisms.size; } } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 336f6b7..f3a1cca 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -27,11 +27,11 @@ class Organisms extends BaseOrganisms { constructor(manager) { super(manager); this._onStepInCb = this._onStepIn.bind(this); - this.manager.on(EVENTS.STEP_IN, this._onStepInCb); + this.parent.on(EVENTS.STEP_IN, this._onStepInCb); } destroy() { - this.manager.off(EVENTS.STEP_IN, this._onStepInCb); + this.parent.off(EVENTS.STEP_IN, this._onStepInCb); this._onStepInCb = null; super.destroy(); } @@ -64,6 +64,7 @@ class Organisms extends BaseOrganisms { */ onClone(org, child) { const percent = org.cloneEnergyPercent; + if (percent === 0.0) {return} let energy = (((org.energy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() // // This is very special/rare case, when organisms cheating by creating @@ -101,11 +102,11 @@ class Organisms extends BaseOrganisms { * @override */ onAfterKillOrg(org) { - delete this.manager.positions[org.posId]; + delete this.parent.positions[org.posId]; } /** - * Is called after moving of organism is done. Updates this.manager.positions + * Is called after moving of organism is done. Updates this.parent.positions * map with a new position of organism * @param {Number} x1 Start X position * @param {Number} y1 Start Y position @@ -117,8 +118,8 @@ class Organisms extends BaseOrganisms { */ onAfterMove(x1, y1, x2, y2, org) { if (x1 !== x2 || y1 !== y2) { - delete this.manager.positions[Helper.posId(x1, y1)]; - this.manager.positions[Helper.posId(x2, y2)] = org; + delete this.parent.positions[Helper.posId(x1, y1)]; + this.parent.positions[Helper.posId(x2, y2)] = org; } return true; @@ -128,16 +129,16 @@ class Organisms extends BaseOrganisms { if (x < 0 || y < 0 || !Number.isInteger(x) || !Number.isInteger(y)) {return} const posId = Helper.posId(x, y); - if (typeof(this.manager.positions[posId]) === 'undefined') { - ret.ret = this.manager.world.getDot(x, y) + if (typeof(this.parent.positions[posId]) === 'undefined') { + ret.ret = this.parent.world.getDot(x, y) } else { - ret.ret = this.manager.positions[posId].energy; + ret.ret = this.parent.positions[posId].energy; } } _onEat(org, x, y, ret) { - const world = this.manager.world; - const positions = this.manager.positions; + const world = this.parent.world; + const positions = this.parent.positions; let dir; [x, y, dir] = Helper.normalize(x, y); @@ -153,7 +154,7 @@ class Organisms extends BaseOrganisms { _onStep(org, x1, y1, x2, y2, ret) { if (org.alive === false) {return} - const man = this.manager; + const man = this.parent; let dir; [x2, y2, dir] = Helper.normalize(x2, y2); @@ -210,7 +211,7 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.manager.world.isFree(x, y) && this.organisms.size < OConfig.orgMaxOrgs && this.createOrg({x, y})) { + if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < OConfig.orgMaxOrgs && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); org.grabEnergy(OConfig.orgStepEnergySpendPercent); @@ -219,7 +220,7 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - this.manager.world.setDot(org.x, org.y, org.color); + this.parent.world.setDot(org.x, org.y, org.color); } } @@ -227,8 +228,8 @@ class Organisms extends BaseOrganisms { let dir; [x, y, dir] = Helper.normalize(x, y); - if (typeof(this.manager.positions[Helper.posId(x, y)]) === 'undefined') { - ret.ret = this.manager.world.getDot(x, y) > 0 ? ENERGY : EMPTY; + if (typeof(this.parent.positions[Helper.posId(x, y)]) === 'undefined') { + ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; } else { ret.ret = ORGANISM; } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 9c78e7c..e1cf5f7 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -44,11 +44,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920, + worldWidth: 384, /** * {Number} World height */ - worldHeight: 1080, + worldHeight: 216, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -57,7 +57,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -75,13 +75,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.5, + worldEnergyCheckPercent: 0.3, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 8000, + worldEnergyCheckPeriod: 15000, /** * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages From 893afa31fe00afaa3fea88531f40682be3d0abf0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 6 Jan 2018 12:30:07 +0200 Subject: [PATCH 093/291] fixed an issue of disconnected server. client tried to send messages to undefined server #13 --- client/src/manager/Manager.js | 8 ++++++++ client/src/manager/plugins/client/Client.js | 1 + client/src/share/Config.js | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 663fac8..bfe316b 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -161,6 +161,14 @@ class Manager extends Observer { return this._activeAround.indexOf(true) !== -1; } + /** + * Resets active around clients/Managers. It means, that connection with + * server has closed or interrupted + */ + resetActive() { + for (let i = 0, active = this._activeAround, len = active.length; i < len; i++) {active[i] = false} + } + destroy(done = () => {}) { if (this._active || this._stopping) { this._destroying = true; diff --git a/client/src/manager/plugins/client/Client.js b/client/src/manager/plugins/client/Client.js index c69bab4..b053ec3 100644 --- a/client/src/manager/plugins/client/Client.js +++ b/client/src/manager/plugins/client/Client.js @@ -79,6 +79,7 @@ class Client extends BaseClient { super.onClose(event); Console.warn(`Client "${this._manager.clientId}" has disconnected by reason: ${this.closeReason}`); this._manager.clientId = null; + this._manager.resetActive(); } /** diff --git a/client/src/share/Config.js b/client/src/share/Config.js index e1cf5f7..162a222 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -101,7 +101,7 @@ ClientConfig.init({ /** * {String} Host for connecting with server */ - serverHost: 'ws://127.0.0.1'//'ws://192.168.31.176' + serverHost: 'ws://192.168.31.176' }); module.exports = {Config: ClientConfig.cfg(), api: ClientConfig}; \ No newline at end of file From 4c0750e58b946594d19e1bd0e567d4739179f074 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 6 Jan 2018 12:30:52 +0200 Subject: [PATCH 094/291] added local and remote IP addresses of clients and server in a log --- server/src/server/Server.js | 31 +++++++++++++++++++++++++++++-- server/src/server/plugins/Api.js | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/server/src/server/Server.js b/server/src/server/Server.js index ed5fb79..cef9c3f 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -29,6 +29,7 @@ * * @author flatline */ +const OS = require('os'); const WebSocket = require('./../../../node_modules/ws/index'); const Connection = require('./../../../common/src/net/Connection').Connection; const EVENTS = require('./../../../common/src/net/Connection').EVENTS; @@ -112,7 +113,7 @@ class Server extends Connection { this.active = true; this._running = false; this.fire(RUN); - Console.info('Server is ready'); + Console.info(`Server is ready on ${this._getIp()}:${this._port}`); }; this.aroundServers && this.aroundServers.run(onDone) || onDone(); }); @@ -197,8 +198,9 @@ class Server extends Connection { * regions for new connections, then places current one in a connection * cub and sends unique id to the client. * @param {WebSocket} sock Client's socket + * @param {Object} req Request info object */ - onConnect(sock) { + onConnect(sock, req) { const region = this.conns.getFreeRegion(); const clientId = Connections.toId(region); if (region === null && this._server.clients.length > Config.maxConnections + 4) { // 4 extra connections for near servers @@ -207,6 +209,12 @@ class Server extends Connection { Console.warn('This server is overloaded by clients. Try another server to connect.'); return; } + // + // This is small hack. We have to bind remote client address and + // it's socket. We use this info in a terminal to show remote + // connected client address + // + sock.remoteAddr = req.connection.remoteAddress; sock.on('message', this.onMessage.bind(this, sock)); sock.on('error', this.onError.bind(this, clientId, sock)); @@ -236,6 +244,25 @@ class Server extends Connection { servers && servers.setSocket(sock, dir); clientId !== false && Console.warn(`Client [${isServer ? NAMES[dir] : clientId}] has disconnected by reason: ${this.closeReason}`); } + + /** + * Returns local IP, which is used by clients to connect + * @return {String} + */ + _getIp() { + const iFaces = OS.networkInterfaces(); + let ip = '127.0.0.1'; + + Object.keys(iFaces).forEach(dev => { + iFaces[dev].filter(details => { + if (details.family === 'IPv4' && details.internal === false) { + ip = details.address; + } + }); + }); + + return ip; + } } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index da965ea..479b51d 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -116,7 +116,7 @@ class Api extends BaseApi { this.parent.conns.setData(region, 'sock', sock); this._setActive(clientId, true); this.parent.response(sock, TYPES.RES_GET_ID_OK, reqId, clientId); - Console.info(`Client ${clientId} has connected`); + Console.info(`Client ${sock.remoteAddr} has connected on a position [${clientId}]`); } /** From 9a5f3614dd2b846d08d6c5a16bd0e32812194b4f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 6 Jan 2018 13:44:07 +0200 Subject: [PATCH 095/291] added personal cloning for organisms returned individual coloring of organisms --- .../src/manager/plugins/organisms/Config.js | 31 +++++++----- .../src/manager/plugins/organisms/Mutator.js | 8 ++- .../src/manager/plugins/organisms/Organism.js | 50 +++++++++++++------ .../manager/plugins/organisms/Organisms.js | 5 ++ 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index c1bd374..f20ea73 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -9,6 +9,10 @@ const Config = { * in mutations of org.mutationPeriod parameter */ ORG_MAX_MUTATION_PERIOD: 10000, + /** + * {Number} Maximum amount of iterations for clone period + */ + ORG_MAX_CLONE_PERIOD: 10000, /** * {Number} Index of first color of organism. After maximum color this * color will be applied @@ -33,19 +37,20 @@ const Config = { * bigger then other, then it will be decreased to zero lines * of vm and organism will die. * Format: [ - * add - Probability of adding new line to the code - * change - Probability of changing existing line of code - * delete - Probability of deleting a line of code - * small-change - Probability of "small change" - change part of one code line - * clone - Probability for sharing of energy percent on clone - * copy - Probability of copying of code lines inside it's own code - * period - Probability of period of organism mutations - * amount - Probability of amount of mutations per period - * probs - Probability of change one of probability coefficient in this array - * clonePeriod - Probability of change clone energy percent value + * add - Probability of adding new line to the code + * change - Probability of changing existing line of code + * delete - Probability of deleting a line of code + * small-change - Probability of "small change" - change part of one code line + * clone - Probability for sharing of energy percent on clone + * copy - Probability of copying of code lines inside it's own code + * period - Probability of period of organism mutations + * amount - Probability of amount of mutations per period + * probs - Probability of change one of probability coefficient in this array + * clone-percent - Probability of change clone energy percent value + * clone-period - Probability of change clone period value * ] */ - orgMutationProbs: [10,1,1,100,1,1,1,1,1,1], + orgMutationProbs: [10,1,1,100,1,1,1,1,1,1,1], /** * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) @@ -54,7 +59,7 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 30, + orgClonePeriod: 300, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off @@ -128,7 +133,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 5000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 9459c82..7781bf1 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -89,6 +89,11 @@ class Mutator { org.changes++; } + static _onClonePeriod(org) { + org.clonePeriod = Helper.rand(OConfig.ORG_MAX_CLONE_PERIOD); + org.changes++; + } + constructor(manager) { this._manager = manager; this._MUTATION_TYPES = [ @@ -101,7 +106,8 @@ class Mutator { Mutator._onPeriod, Mutator._onAmount, Mutator._onProbs, - Mutator._onCloneEnergyPercent + Mutator._onCloneEnergyPercent, + Mutator._onClonePeriod ]; manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index bfab474..75081bd 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -72,18 +72,20 @@ class Organism extends Observer { get mutationPeriod() {return this._mutationPeriod} get mutationPercent() {return this._mutationPercent} get cloneMutationPercent() {return this._cloneMutationPercent} + get cloneEnergyPercent() {return this._cloneEnergyPercent} + get clonePeriod() {return this._clonePeriod} get energy() {return this._energy} get color() {return this._color} get mem() {return this._mem} - get cloneEnergyPercent() {return this._cloneEnergyPercent} get posId() {return Helper.posId(this._x, this._y)} set x(newX) {this._x = newX} set y(newY) {this._y = newY} set cloneMutationPercent(m) {this._cloneMutationPercent = m} + set cloneEnergyPercent(p) {this._cloneEnergyPercent = p} + set clonePeriod(p) {this._clonePeriod = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set cloneEnergyPercent(p) {this._cloneEnergyPercent = p} set energy(e) {this._energy = e} set changes(c) { this._changes = c; @@ -99,8 +101,15 @@ class Organism extends Observer { this._iterations++; if (this.onBeforeRun() === false) {return true} this.onRun(); - this.alive && this.vm.size === 0 && this._onCodeEnd(this, 0); - return this.alive && this._updateDestroy() && this._updateEnergy(); + + if (this.alive) { + this.vm.size === 0 && this._onCodeEnd(this, 0); + this._updateClone(); + this.alive && this._updateDestroy(); + this.alive && this._updateEnergy(); + } + + return true; } /** @@ -122,9 +131,10 @@ class Organism extends Observer { color : this._color, mutationProbs : this._mutationProbs, cloneMutationPercent: this._cloneMutationPercent, + cloneEnergyPercent : this._cloneEnergyPercent, + clonePeriod : this._clonePeriod, mutationPeriod : this._mutationPeriod, mutationPercent : this._mutationPercent, - cloneEnergyPercent : this._cloneEnergyPercent, mem : this.mem.slice() }; @@ -152,9 +162,10 @@ class Organism extends Observer { this._color = json.color; this._mutationProbs = json.mutationProbs; this._cloneMutationPercent = json.cloneMutationPercent; + this._cloneEnergyPercent = json.cloneEnergyPercent; + this._clonePeriod = json.clonePeriod; this._mutationPeriod = json.mutationPeriod; this._mutationPercent = json.mutationPercent; - this._cloneEnergyPercent = json.cloneEnergyPercent; this._mem = json.mem.slice(); } @@ -186,10 +197,9 @@ class Organism extends Observer { } _updateColor(changes) { - // TODO: tempoorary solution to have red organisms all the time - // if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { - // this._color = OConfig.ORG_FIRST_COLOR; - // } + if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { + this._color = OConfig.ORG_FIRST_COLOR; + } } _create() { @@ -198,9 +208,10 @@ class Organism extends Observer { this._color = OConfig.orgStartColor; this._mutationProbs = OConfig.orgMutationProbs.slice(); this._cloneMutationPercent = OConfig.orgCloneMutationPercent; + this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; + this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; - this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; this._changes = 1; this._mem = []; } @@ -211,9 +222,10 @@ class Organism extends Observer { this._color = parent.color; this._mutationProbs = parent.mutationProbs.slice(); this._cloneMutationPercent = parent.cloneMutationPercent; + this._cloneEnergyPercent = parent.cloneEnergyPercent; + this._clonePeriod = parent.clonePeriod; this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; - this._cloneEnergyPercent = parent.cloneEnergyPercent; this._changes = parent.changes; this._mem = parent.mem.slice(); } @@ -232,8 +244,8 @@ class Organism extends Observer { } /** - * This is how our system grabs an energy= require(organism if it's age is - * divided into OConfig.orgEnergySpendPeriod. + * This is how our system grabs an energy from organism every OConfig.orgEnergySpendPeriod + * period. * @return {Boolean} false means that organism was destroyed. */ _updateEnergy() { @@ -243,6 +255,16 @@ class Organism extends Observer { return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } + + /** + * Current organism wants to clone himself + * @return {Boolean} + */ + _updateClone() { + if (this._iterations % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0) {return true} + this.fire(EVENTS.CLONE, this); + return true; + } } module.exports = Organism; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 2f01d39..eff7236 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -110,6 +110,7 @@ class Organisms extends Configurable { addOrgHandlers(org) { org.on(EVENTS.DESTROY, this._onKillOrg.bind(this)); + org.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); } /** @@ -287,6 +288,10 @@ class Organisms extends Configurable { //Console.info(org.id, ' die'); } + _onCloneOrg(org) { + org.alive && this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); + } + /** * API method, which will be added to Manager.api interface * @return {Number} Amount of organisms within current Manager From 7173da08dc3eb42f1ecee955cc8d9017007c88c4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 6 Jan 2018 18:18:38 +0200 Subject: [PATCH 096/291] fixed an issue with extra client #13 added connections arrows at the top left corner --- client/src/manager/plugins/status/Status.js | 3 ++- client/src/share/Config.js | 2 +- server/src/server/Server.js | 4 ++-- server/src/server/plugins/Api.js | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 126ece3..e906c41 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -81,7 +81,8 @@ class Status extends Configurable { const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); - man.canvas && man.canvas.text(5, 20, sips + (man.clientId && man.clientId || '')); + const active = man.activeAround; + man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); this._onAfterLog(stamp); } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 162a222..6ee158f 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -75,7 +75,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.3, + worldEnergyCheckPercent: 0.5, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if diff --git a/server/src/server/Server.js b/server/src/server/Server.js index cef9c3f..78c318a 100644 --- a/server/src/server/Server.js +++ b/server/src/server/Server.js @@ -237,12 +237,12 @@ class Server extends Connection { const dir = servers ? servers.getDirection(sock) : clientId; const isServer = dir < DIR.NO; - !isServer && this.conns.clearData(region); + !isServer && region && this.conns.clearData(region); sock.removeAllListeners('message'); sock.removeAllListeners('error'); sock.removeAllListeners('close'); servers && servers.setSocket(sock, dir); - clientId !== false && Console.warn(`Client [${isServer ? NAMES[dir] : clientId}] has disconnected by reason: ${this.closeReason}`); + Console.warn(`Client [${isServer ? NAMES[dir] : (clientId || sock.remoteAddr)}] has disconnected by reason: ${this.closeReason}`); } /** diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 479b51d..3da1fda 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -16,6 +16,7 @@ const DIR = require('./../../../../common/src/Directions').DIR; const FLIP_DIR = require('./../../../../common/src/Directions').FLIP_DIR; const NAMES = require('./../../../../common/src/Directions').NAMES; const BaseApi = require('./../../../../common/src/net/Api'); + class Api extends BaseApi { constructor(parent) { super(parent); From 0061c69b6be240cdd1616fe3d68a62d74073dbe1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 7 Jan 2018 12:41:54 +0200 Subject: [PATCH 097/291] Iiihhhhaaaa!!! great commit! significantly improved evolution speed by moving cloning ability personally to every organism added a possibility to create separate organisms types within one world/manager added worldNoScrolls config fixed an issue with incorrect world energy calculation fixed changes related logs in Status --- client/src/manager/Manager.js | 2 +- client/src/manager/plugins/Energy.js | 2 +- .../src/manager/plugins/organisms/Config.js | 14 +++---- .../src/manager/plugins/organisms/Organism.js | 12 +++--- .../manager/plugins/organisms/Organisms.js | 41 +++++++++---------- client/src/manager/plugins/status/Status.js | 17 ++++---- client/src/share/Config.js | 8 +++- client/src/view/Canvas.js | 6 ++- 8 files changed, 53 insertions(+), 49 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index bfe316b..22af1e2 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -67,7 +67,7 @@ class Manager extends Observer { this._codeRuns = 0; this._world = new World(Config.worldWidth, Config.worldHeight); - this._canvas = hasView && new Canvas(Config.worldWidth, Config.worldHeight) || null; + this._canvas = hasView && new Canvas(Config.worldWidth, Config.worldHeight, Config.worldNoScrolls) || null; this._visualized = true; this._running = false; this._active = false; diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 488313f..7d9832a 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -39,7 +39,7 @@ class Energy { } } - if (energy * 100 / (width * height) <= Config.worldEnergyCheckPercent) { + if (energy / (width * height) <= Config.worldEnergyCheckPercent) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index f20ea73..35b0162 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -59,12 +59,12 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 300, + orgClonePeriod: 100, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 3000, + orgCrossoverPeriod: 300, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -85,7 +85,7 @@ const Config = { * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 100000, + orgStartEnergy: 50000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB @@ -95,12 +95,12 @@ const Config = { * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. */ - orgEnergySpendPeriod: 20, + orgEnergySpendPeriod: 10, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 20000, + orgAlivePeriod: 10000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -113,7 +113,7 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 5, + orgGarbagePeriod: 6, /** * {Number} Size of organism stack (internal memory) */ @@ -133,7 +133,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 5000, + orgMaxOrgs: 1000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 75081bd..0f7ba2a 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -196,12 +196,6 @@ class Organism extends Observer { super.destroy(); } - _updateColor(changes) { - if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { - this._color = OConfig.ORG_FIRST_COLOR; - } - } - _create() { this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls); this._energy = OConfig.orgStartEnergy; @@ -230,6 +224,12 @@ class Organism extends Observer { this._mem = parent.mem.slice(); } + _updateColor(changes) { + if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { + this._color = OConfig.ORG_FIRST_COLOR; + } + } + /** * Checks if organism need to be killed/destroyed, because of age or zero energy * @return {Boolean} false means that organism was destroyed. diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index eff7236..3618230 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -113,26 +113,6 @@ class Organisms extends Configurable { org.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); } - /** - * Cloning parents are chosen according to tournament principle - * @param {Number} counter Current counter - * @returns {boolean} - */ - updateClone(counter) { - const needClone = counter % OConfig.orgClonePeriod === 0 && OConfig.orgClonePeriod !== 0; - let orgAmount = this.organisms.size; - if (!needClone || orgAmount >= OConfig.orgMaxOrgs || orgAmount < 1) {return false} - let org1 = this.randOrg(); - let org2 = this.randOrg(); - if (!org1.alive && !org2.alive || org1 === org2) {return false} - - let tmpOrg = this._tournament(org1, org2); - if (tmpOrg === org2) {[org1, org2] = [org2, org1]} - if (org1.alive) {this._clone(org1)} - - return true; - } - updateCrossover(counter) { const orgAmount = this.organisms.size; const needCrossover = counter % OConfig.orgCrossoverPeriod === 0 && OConfig.orgCrossoverPeriod !== 0; @@ -218,7 +198,6 @@ class Organisms extends Configurable { item = item.next; } - this.updateClone(counter); this.updateCrossover(counter); } @@ -289,7 +268,25 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - org.alive && this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); + this._updateAmount() && this._clone(org); + } + + /** + * Does tournament between two random organisms and kill looser, if amount of + * organisms is greater or equal to maximum (OConfig.orgMaxOrgs). In general + * this function is a natural selection in our system. + * @returns {Boolean} true - amount is less then maximum, false - otherwise + */ + _updateAmount() { + let orgAmount = this.organisms.size; + if (orgAmount < OConfig.orgMaxOrgs || orgAmount < 1) {return true} + let org1 = this.randOrg(); + let org2 = this.randOrg(); + if (!org1.alive || !org2.alive || org1 === org2) {return false} + + this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); + + return true; } /** diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index e906c41..f52f38c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -72,13 +72,13 @@ class Status extends Configurable { const format = Status._format; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); - const schanges = format(this._changes, 'che', orgAmount, 2, 14, 10000000, true); - const sfit = format(this._fitness, 'fit', orgAmount, 2, 14 ); - const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); + const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); + const schanges = format(this._changes, 'che', orgAmount, 2, 14 ); + const sfit = format(this._fitness, 'fit', orgAmount, 2, 14 ); + const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); const active = man.activeAround; @@ -111,11 +111,10 @@ class Status extends Configurable { } energy /= size; - changes /= size; fitness /= size; this._curEnergy = energy; this._energy = (energy - olds[0]) / lines; - this._changes = (changes - olds[1]) / lines; + this._changes = (changes - olds[1]) / size; this._fitness = (fitness - olds[2]) / lines; this._codeSize = codeSize; this._oldValues = [energy, changes, fitness]; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 6ee158f..6aa56e8 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -75,13 +75,17 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.5, + worldEnergyCheckPercent: 0.1, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 15000, + worldEnergyCheckPeriod: 10000, + /** + * {Boolean} Turns on/off scroll bars in a 2D canvas + */ + worldNoScrolls: true, /** * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 30d6b33..5e32b8a 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -4,13 +4,17 @@ * @author flatline */ class Canvas { - constructor(width, height) { + constructor(width, height, noScrolls = false) { const id = 'world'; const doc = document; const bodyEl = doc.body; this._prepareDom(); bodyEl.innerHTML += ``; + // + // This style hides scroll bars on full screen 2d canvas + // + if (noScrolls) {document.querySelector('html').style.overflow = 'hidden'} this._id = id; this._width = width; From caf42a2f022f0b17b96bedfe0ee40806c8177379 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 00:43:43 +0200 Subject: [PATCH 098/291] changed default configuration of the world and mutations period --- client/src/manager/plugins/organisms/Config.js | 6 +++--- client/src/share/Config.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 35b0162..4ba6331 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -70,7 +70,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 3000, + orgRainMutationPeriod: 300, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -100,7 +100,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 10000, + orgAlivePeriod: 30000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -133,7 +133,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 200, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 6aa56e8..1c131e4 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -44,11 +44,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 384, + worldWidth: 1920, /** * {Number} World height */ - worldHeight: 216, + worldHeight: 1080, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 From cf7f564cbaf5ce79ad8099e6761742d847606248 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 13:26:31 +0200 Subject: [PATCH 099/291] fixed Status parameters representation issue --- client/src/manager/plugins/status/Status.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index f52f38c..9e6b15f 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -27,8 +27,8 @@ const RED = 'color: #aa0000'; class Status extends Configurable { static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = false) { - orgs = perOrg ? orgs : 1; - return `${name}:${((value / orgs) * coef).toFixed(fixed)}`.padEnd(pad); + const val = (value / (perOrg ? orgs : 1)) * coef; + return `${name}:${val.toFixed(fixed === -1 && 2 || (val < 10 && val > -10 ? fixed : 0))}`.padEnd(pad); } constructor(manager) { @@ -72,13 +72,13 @@ class Status extends Configurable { const format = Status._format; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); - const schanges = format(this._changes, 'che', orgAmount, 2, 14 ); - const sfit = format(this._fitness, 'fit', orgAmount, 2, 14 ); - const scode = format(this._codeSize, 'cod', orgAmount, 1, 12, 1, true); + const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); + const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); + const sfit = format(this._fitness, 'fit', orgAmount, 2, 12 ); + const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); const active = man.activeAround; From 30952052276d3d0b6ae2c3d96cab2eada7efee18 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 15:34:27 +0200 Subject: [PATCH 100/291] fixed common age of organisms --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/organisms/Organisms.js | 8 ++++---- client/src/manager/plugins/status/Status.js | 9 +++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4ba6331..4ee834e 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -100,7 +100,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 30000, + orgAlivePeriod: 5000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 3618230..ef0dc2e 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -122,7 +122,7 @@ class Organisms extends Configurable { let org2 = this._tournament(); if (!org1.alive || !org2.alive) {return false} - this._crossover(org1, org2); + this._updateAmount() && this._crossover(org1, org2); return true; } @@ -268,7 +268,7 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - this._updateAmount() && this._clone(org); + this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); } /** @@ -279,10 +279,10 @@ class Organisms extends Configurable { */ _updateAmount() { let orgAmount = this.organisms.size; - if (orgAmount < OConfig.orgMaxOrgs || orgAmount < 1) {return true} + if (orgAmount < OConfig.orgMaxOrgs) {return true} let org1 = this.randOrg(); let org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2) {return false} + if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 9e6b15f..5cd38a9 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -42,6 +42,7 @@ class Status extends Configurable { this._changes = 0; this._codeSize = 0; this._runLines = 1; + this._age = 0; this._times = 0; this._oldValues = [0, 0, 0]; this._onIpsCb = this._onIps.bind(this); @@ -77,10 +78,11 @@ class Status extends Configurable { const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); - const sfit = format(this._fitness, 'fit', orgAmount, 2, 12 ); + const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); + const sage = format(this._age, 'age', orgAmount, 0, 11, 1, true); const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); - console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${scode}`, GREEN, RED); + console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); const active = man.activeAround; man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); this._onAfterLog(stamp); @@ -98,6 +100,7 @@ class Status extends Configurable { let energy = 0; let fitness = 0; let changes = 0; + let age = 0; let codeSize = 0; let item = orgs.first; let org; @@ -106,6 +109,7 @@ class Status extends Configurable { energy += org.energy; changes += org.changes; fitness += org.fitness(); + age += org.iterations; codeSize += org.vm.size; item = item.next; } @@ -117,6 +121,7 @@ class Status extends Configurable { this._changes = (changes - olds[1]) / size; this._fitness = (fitness - olds[2]) / lines; this._codeSize = codeSize; + this._age = age; this._oldValues = [energy, changes, fitness]; } From 8cea555c547ab7e2ac2429ba552a5ce2015070b0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 16:41:53 +0200 Subject: [PATCH 101/291] small fixes --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/share/Config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 35b0162..1bbf09b 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -70,7 +70,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 3000, + orgRainMutationPeriod: 300, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 6aa56e8..0084ec4 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -105,7 +105,7 @@ ClientConfig.init({ /** * {String} Host for connecting with server */ - serverHost: 'ws://192.168.31.176' + serverHost: 'ws://127.0.0.1'//'ws://192.168.31.176' }); module.exports = {Config: ClientConfig.cfg(), api: ClientConfig}; \ No newline at end of file From 9594f4669889fb95b812312f6766eabb9fb06a8e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 18:47:19 +0200 Subject: [PATCH 102/291] implemented tournament regulated organisms amount (added orgTournamentPeriod config) --- .../src/manager/plugins/organisms/Config.js | 9 ++- .../manager/plugins/organisms/Organisms.js | 65 ++++++++++--------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4ee834e..2cda0e8 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -65,6 +65,13 @@ const Config = { * to random organisms. May be set to 0 to turn crossover off */ orgCrossoverPeriod: 300, + /** + * {Number} Period of tournament between organisms. If amount of organisms + * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This + * is how natural selection is implemented in our system. Set this parameter + * to 0 and tournament mechanism will be turned off + */ + orgTournamentPeriod: 100, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -133,7 +140,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 800, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index ef0dc2e..95c4a30 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -113,26 +113,6 @@ class Organisms extends Configurable { org.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); } - updateCrossover(counter) { - const orgAmount = this.organisms.size; - const needCrossover = counter % OConfig.orgCrossoverPeriod === 0 && OConfig.orgCrossoverPeriod !== 0; - if (!needCrossover || orgAmount >= OConfig.orgMaxOrgs || orgAmount < 1) {return false} - - let org1 = this._tournament(); - let org2 = this._tournament(); - - if (!org1.alive || !org2.alive) {return false} - this._updateAmount() && this._crossover(org1, org2); - - return true; - } - - updateCreate() { - if (this.organisms.size < 1) { - this._createPopulation(); - } - } - reset() { this._orgId = 0; } @@ -198,11 +178,12 @@ class Organisms extends Configurable { item = item.next; } - this.updateCrossover(counter); + this._updateAmount(counter); + this._updateCrossover(counter); } _onLoop() { - this.updateCreate(); + this._updateCreate(); } _tournament(org1 = null, org2 = null) { @@ -249,6 +230,14 @@ class Organisms extends Configurable { Console.info('Population has created'); } + /** + * API method, which will be added to Manager.api interface + * @return {Number} Amount of organisms within current Manager + */ + _apiGetAmount() { + return this.parent.organisms.size; + } + _onCodeEnd(org, lines) { this.parent.codeRuns++; this.parent.fire(EVENTS.ORGANISM, org, lines); @@ -271,15 +260,35 @@ class Organisms extends Configurable { this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); } + _updateCrossover(counter) { + const orgAmount = this.organisms.size; + if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgCrossoverPeriod !== 0 && OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} + + let org1 = this._tournament(); + let org2 = this._tournament(); + + if (!org1.alive || !org2.alive) {return false} + this._crossover(org1, org2); + + return true; + } + + _updateCreate() { + if (this.organisms.size < 1) { + this._createPopulation(); + } + } + /** * Does tournament between two random organisms and kill looser, if amount of * organisms is greater or equal to maximum (OConfig.orgMaxOrgs). In general * this function is a natural selection in our system. + * @param {Number} counter Current value of global iterations counter * @returns {Boolean} true - amount is less then maximum, false - otherwise */ - _updateAmount() { + _updateAmount(counter) { let orgAmount = this.organisms.size; - if (orgAmount < OConfig.orgMaxOrgs) {return true} + if (counter % OConfig.orgTournamentPeriod !== 0 || orgAmount < 1 || OConfig.orgTournamentPeriod === 0) {return true} let org1 = this.randOrg(); let org2 = this.randOrg(); if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} @@ -288,14 +297,6 @@ class Organisms extends Configurable { return true; } - - /** - * API method, which will be added to Manager.api interface - * @return {Number} Amount of organisms within current Manager - */ - _apiGetAmount() { - return this.parent.organisms.size; - } } module.exports = Organisms; \ No newline at end of file From 92f89021cc0207e4b91ad52f7911981f99206aad Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 19:32:54 +0200 Subject: [PATCH 103/291] changed default configs --- client/src/manager/plugins/organisms/Config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 2cda0e8..986253c 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -71,7 +71,7 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 100, + orgTournamentPeriod: 80, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -140,7 +140,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 800, + orgMaxOrgs: 200, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, From 68296f4e65ce85a90237fec775429f004d165003 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 21:45:52 +0200 Subject: [PATCH 104/291] fixed tests #83 --- common/src/Observer.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/src/Observer.js b/common/src/Observer.js index 36d378b..ea1c2e9 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -35,8 +35,10 @@ class Observer { let index; let handlers = this._handlers[event]; - if ((index = handlers.indexOf(handler)) < 0) {return false} - handlers.splice(index, 1); + if (handlers) { + if ((index = handlers.indexOf(handler)) < 0) {return false} + handlers.splice(index, 1); + } return true; } From 70508d5b4696cfb49f0c4c248916ebe4c2bb574d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 8 Jan 2018 22:09:28 +0200 Subject: [PATCH 105/291] changed step functions. from now they return moved coordinates --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/organisms/dos/Operators.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 986253c..2fdf652 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -140,7 +140,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 300, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 8febd12..6722f7c 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -192,10 +192,10 @@ class OperatorsDos extends Operators { onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} - onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y); return ++line} - onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y); return ++line} - onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1); return ++line} - onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1); return ++line} + onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; return ++line} + onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; return ++line} + onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; return ++line} + onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} onFromMem(num, line, org) {this.vars[VAR0(num)] = org.mem.pop() || 0; return ++line} onToMem(num, line, org) { @@ -247,7 +247,7 @@ class OperatorsDos extends Operators { org.y = ret.y; } - return ret.ret; + return ret; } /** From 98737900213af7c305c3020dc516bc01af9af539 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 9 Jan 2018 01:25:42 +0200 Subject: [PATCH 106/291] fixed small issue of sending organism back to source client #13 fixed issue with incorrect average age calculation --- .../src/manager/plugins/client/plugins/Api.js | 17 ++++++++++++++- .../src/manager/plugins/organisms/Config.js | 4 ++-- client/src/manager/plugins/status/Status.js | 21 +++++++++++++------ common/src/Helper.js | 21 +++++++++++++++++++ server/src/server/plugins/Api.js | 11 +++------- 5 files changed, 57 insertions(+), 17 deletions(-) diff --git a/client/src/manager/plugins/client/plugins/Api.js b/client/src/manager/plugins/client/plugins/Api.js index 30a1cb1..2628eef 100644 --- a/client/src/manager/plugins/client/plugins/Api.js +++ b/client/src/manager/plugins/client/plugins/Api.js @@ -13,7 +13,7 @@ class Api extends BaseApi { super(client); this.api[TYPES.REQ_MOVE_ORG] = this._stepIn.bind(this); - this.api[TYPES.REQ_MOVE_ORG_BACK] = this._stepIn.bind(this); + this.api[TYPES.REQ_MOVE_ORG_BACK] = this._stepInBack.bind(this); this.api[TYPES.REQ_SET_NEAR_ACTIVE] = this._setActive.bind(this); } @@ -38,6 +38,21 @@ class Api extends BaseApi { this.parent.response(this.sock, ret.ret ? TYPES.RES_MOVE_OK : TYPES.RES_MOVE_ERR, reqId, clientId); } + /** + * Is called if organism is moved back from other Manager (world) + * @param {String} reqId Unique request id + * @param {String} clientId Unique client id within current server + * @param {Number} x Current org X position + * @param {Number} y Current org Y position + * @param {Number} dir Direction of moving + * @param {String} orgJson Organism's serialized json + * @api + */ + _stepInBack(reqId, clientId, x, y, dir, orgJson) { + const ret = {ret: true}; + this.parent.manager.fire(EVENTS.STEP_IN, x, y, orgJson, ret); + } + /** * Is called to set active flag of nearest manager/client. After * setting it to true, nearest client/Manager may pass it's organisms diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 2fdf652..4b3a0b5 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -107,7 +107,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 5000, + orgAlivePeriod: 3000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -140,7 +140,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 1000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 5cd38a9..36e8128 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -43,20 +43,25 @@ class Status extends Configurable { this._codeSize = 0; this._runLines = 1; this._age = 0; + this._ageCount = 0; this._times = 0; this._oldValues = [0, 0, 0]; this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); + this._onKillOrgCb = this._onKillOrg.bind(this); manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.ORGANISM, this._onOrganismCb); + manager.on(EVENTS.KILL_ORGANISM, this._onKillOrgCb); } destroy() { - this._manager.off(EVENTS.IPS, this._onIpsCb); + this._manager.off(EVENTS.KILL_ORGANISM, this._onKillOrgCb); this._manager.off(EVENTS.ORGANISM, this._onOrganismCb); - this._onIpsCb = null; + this._manager.off(EVENTS.IPS, this._onIpsCb); + this._onKillOrgCb = null; this._onOrganismCb = null; + this._onIpsCb = null; this._manager = null; this._oldValues = null; super.destroy(); @@ -79,7 +84,7 @@ class Status extends Configurable { const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); - const sage = format(this._age, 'age', orgAmount, 0, 11, 1, true); + const sage = format(this._age / this._ageCount, 'age', orgAmount, 0, 11, 1 ); const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); @@ -93,6 +98,11 @@ class Status extends Configurable { this._runLines += lines; } + _onKillOrg(org) { + this._age += org.iterations; + this._ageCount++; + } + _onBeforeLog(ips, orgs) { const olds = this._oldValues; const size = orgs.size || 1; @@ -100,7 +110,6 @@ class Status extends Configurable { let energy = 0; let fitness = 0; let changes = 0; - let age = 0; let codeSize = 0; let item = orgs.first; let org; @@ -109,7 +118,6 @@ class Status extends Configurable { energy += org.energy; changes += org.changes; fitness += org.fitness(); - age += org.iterations; codeSize += org.vm.size; item = item.next; } @@ -121,13 +129,14 @@ class Status extends Configurable { this._changes = (changes - olds[1]) / size; this._fitness = (fitness - olds[2]) / lines; this._codeSize = codeSize; - this._age = age; this._oldValues = [energy, changes, fitness]; } _onAfterLog(stamp) { this._times = 0; this._runLines = 0; + this._age = 0; + this._ageCount = 0; this._stamp = stamp; } } diff --git a/common/src/Helper.js b/common/src/Helper.js index 2b0d339..10a54c6 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -66,12 +66,14 @@ class Helper { obj[fnName] = fn.fn; delete fn.fn; } + /** * Generates random Int number in range 0:n-1 * @param {Number} n Right number value in a range * @return {Number} */ static rand(n) {return Math.trunc(Math.random() * n)} + /** * It calculates probability index from variable amount of components. * Let's imagine we have two actions: one and two. We want @@ -104,11 +106,13 @@ class Helper { return i; } + /** * Checks if position is empty. x == y == 0 - this is empty * @param {Object} pos Position to check */ static empty(pos) {return pos.x === 0 && pos.y === 0} + /** * Does normalization of X and Y coordinates. It's used * in cyclical mode for checking if we out of bound (world). @@ -148,6 +152,23 @@ class Helper { return [(dir === DIR.LEFT || dir === DIR.RIGHT) && typeof(xMap[x]) !== 'undefined' ? xMap[x] : x, (dir === DIR.UP || dir === DIR.DOWN) && typeof(yMap[y]) !== 'undefined' ? yMap[y] : y]; } + /** + * Flips region according to moving direction + * @param {Array} region Old region + * @param {Number} dir Moving direction + * @returns {Array} New region + */ + static flipRegion(region, dir) { + const newReg = [region[0], region[1]]; + + if (dir === DIR.UP) {newReg[1]--} + else if (dir === DIR.RIGHT) {newReg[0]++} + else if (dir === DIR.DOWN) {newReg[1]++} + else if (dir === DIR.LEFT) {newReg[0]--} + + return newReg; + } + /** * Analog of jQuery.isNumeric() * @param {*} n Value to check diff --git a/server/src/server/plugins/Api.js b/server/src/server/plugins/Api.js index 3da1fda..abba91e 100644 --- a/server/src/server/plugins/Api.js +++ b/server/src/server/plugins/Api.js @@ -147,14 +147,9 @@ class Api extends BaseApi { * @param {Boolean} fromClient false if organism came from near server */ _moveToClient(back, clientId, x, y, dir, orgJson, fromClient = true) { - const region = Connections.toRegion(clientId); + let region = Connections.toRegion(clientId); - if (fromClient) { - if (dir === DIR.UP) {region[1]--} - else if (dir === DIR.RIGHT) {region[0]++} - else if (dir === DIR.DOWN) {region[1]++} - else if (dir === DIR.LEFT) {region[0]--} - } + if (fromClient) {region = Helper.flipRegion(region, dir)} // // If destination client active, then organism is moved there. // Otherwise, we have to move it back to source client (possibly @@ -199,7 +194,7 @@ class Api extends BaseApi { _moveBack(region, clientId, x, y, dir, orgJson, fromClient) { const newDir = FLIP_DIR[dir]; const parent = this.parent; - const sock = fromClient ? parent.conns.getConnection(region).sock : parent.aroundServers.getSocket(newDir); + const sock = fromClient ? parent.conns.getConnection(Helper.flipRegion(region, newDir)).sock : parent.aroundServers.getSocket(newDir); const newClientId = fromClient ? Connections.toId(region) : clientId; const flipped = Helper.flip(x, y, newDir); sock && parent.request(sock, TYPES.REQ_MOVE_ORG_BACK, newClientId, flipped[0], flipped[1], newDir, orgJson); From 3be038e27cd3efd13cee87611158534d5e8926d2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 9 Jan 2018 02:40:32 +0200 Subject: [PATCH 107/291] fixed an issue of crossing border between clients by organisms --- client/src/manager/plugins/organisms/Config.js | 15 ++++++++++++--- client/src/manager/plugins/organisms/Organisms.js | 2 +- .../manager/plugins/organisms/dos/Organisms.js | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4b3a0b5..97ee7df 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -71,7 +71,7 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 80, + orgTournamentPeriod: 30, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -134,13 +134,22 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.1, + orgStepEnergySpendPercent: 0.5, + /** + * {Number} Percent from orgMaxOrgs config, which is used for crossing borders + * between clients/Managers. Entire amount of organisms within one client = + * orgMaxOrgs + orgMaxOrgs * orgStepOverflowPercent. Without this config organisms + * try to rich the limit of organisms on one client and it's impossible to cross + * the border (every organism will be returned back, but there will not be free + * space at that time). In this situation crossing organism just die during crossing. + */ + orgStepOverflowPercent: 0.1, /** * {Number} Maximum amount of organisms in a world. If some organism will * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 3000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 95c4a30..da8c954 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -131,7 +131,7 @@ class Organisms extends Configurable { createOrg(pos, parent = null) { const orgs = this.organisms; - if (orgs.size >= OConfig.orgMaxOrgs || pos === false) {return false} + if (pos === false) {return false} orgs.add(null); let last = orgs.last; let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, this._onCodeEnd.bind(this), parent); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index f3a1cca..531a19c 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -211,7 +211,7 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < OConfig.orgMaxOrgs && this.createOrg({x, y})) { + if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); org.grabEnergy(OConfig.orgStepEnergySpendPercent); @@ -220,7 +220,7 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - this.parent.world.setDot(org.x, org.y, org.color); + this.parent.world.setDot(x, y, org.color); } } From cc611a1fb7dcc8bb78de7b41c9d238c0bf2846a4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 9 Jan 2018 02:47:19 +0200 Subject: [PATCH 108/291] fixed wrong calculation of punishment for organisms, who cross borders between clients #13 --- client/src/manager/plugins/organisms/Config.js | 4 ++-- client/src/manager/plugins/organisms/dos/Organisms.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 97ee7df..7c4e3d3 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -134,7 +134,7 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.5, + orgStepEnergySpendPercent: 0.3, /** * {Number} Percent from orgMaxOrgs config, which is used for crossing borders * between clients/Managers. Entire amount of organisms within one client = @@ -149,7 +149,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 3000, + orgMaxOrgs: 1000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 531a19c..2380936 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -214,7 +214,7 @@ class Organisms extends BaseOrganisms { if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); - org.grabEnergy(OConfig.orgStepEnergySpendPercent); + org.grabEnergy(org.energy * OConfig.orgStepEnergySpendPercent); // // We have to update organism color and coordinates // From 35d0445aa0b9df48288db573af58d59363e3f8da Mon Sep 17 00:00:00 2001 From: tmptrash Date: Tue, 9 Jan 2018 18:44:57 +0200 Subject: [PATCH 109/291] fixed an issue of zombie organisms and memory leaks #13 --- client/src/manager/plugins/organisms/dos/Organisms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 2380936..d4dc50a 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -214,12 +214,12 @@ class Organisms extends BaseOrganisms { if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); - org.grabEnergy(org.energy * OConfig.orgStepEnergySpendPercent); // // We have to update organism color and coordinates // org.x = x; org.y = y; + org.grabEnergy(org.energy * OConfig.orgStepEnergySpendPercent); this.parent.world.setDot(x, y, org.color); } } From 3814ab163ef39895d7f6745975de37ad0fdb212b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 9 Jan 2018 23:45:26 +0200 Subject: [PATCH 110/291] fixed another issue with zombie organisms #13 --- client/src/manager/plugins/organisms/dos/Organisms.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index d4dc50a..a75e742 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -137,7 +137,7 @@ class Organisms extends BaseOrganisms { } _onEat(org, x, y, ret) { - const world = this.parent.world; + const world = this.parent.world; const positions = this.parent.positions; let dir; @@ -219,8 +219,7 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - org.grabEnergy(org.energy * OConfig.orgStepEnergySpendPercent); - this.parent.world.setDot(x, y, org.color); + org.grabEnergy((((org.energy * OConfig.orgStepEnergySpendPercent) + 0.5) << 1) >>> 1); } } From 464eccb67bd5e76c79e03a51fd62b6e1088515fe Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 10 Jan 2018 00:34:25 +0200 Subject: [PATCH 111/291] fixed few tests #83 --- client/src/manager/ManagerSpec.js | 36 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 91c23aa..0d3a39b 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -233,7 +233,7 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = 0; OConfig.orgClonePeriod = 0; expect(man.organisms.size).toBe(0); - man.on(EVENTS.ITERATION, () => { + man.on(EVENTS.LOOP, () => { if (iterated) {return} expect(man.organisms.size).toBe(1); man.stop(() => { @@ -255,6 +255,7 @@ describe("client/src/manager/Manager", () => { const percent = OConfig.orgCloneMutationPercent; const period1 = OConfig.orgEnergySpendPeriod; const clone = OConfig.orgClonePeriod; + const max = OConfig.orgMaxOrgs; const server = new Server(); const man1 = new Manager(false); delete Config.organisms; @@ -273,6 +274,7 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = percent; OConfig.orgRainMutationPeriod = period; OConfig.orgStartAmount = amount; + OConfig.orgMaxOrgs = max; done(); }); }); @@ -284,18 +286,19 @@ describe("client/src/manager/Manager", () => { OConfig.orgCloneMutationPercent = 0; OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; + OConfig.orgMaxOrgs = 1; expect(man1.clientId).toBe(null); expect(man2.clientId).toBe(null); expect(man1.organisms.size).toBe(0); expect(man2.organisms.size).toBe(0); - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (blocked) {return} expect(man1.organisms.size).toBe(1); if (iterated1 && iterated2) {destroy(); return} iterated1 = true; }); - man2.on(EVENTS.ITERATION, () => { + man2.on(EVENTS.LOOP, () => { if (blocked) {return} expect(man2.organisms.size).toBe(1); if (iterated2 && iterated1) {destroy(); return} @@ -323,6 +326,7 @@ describe("client/src/manager/Manager", () => { const width = Config.worldWidth; const height = Config.worldHeight; const energy = OConfig.orgStartEnergy; + const max = OConfig.orgMaxOrgs; const server = new Server(); Config.worldWidth = 400; Config.worldHeight = 400; @@ -347,6 +351,7 @@ describe("client/src/manager/Manager", () => { OConfig.orgStartAmount = amount; Config.worldWidth = width; Config.worldHeight = height; + OConfig.orgMaxOrgs = max; done(); }); }); @@ -359,9 +364,10 @@ describe("client/src/manager/Manager", () => { OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; OConfig.orgStartEnergy = 10000; + OConfig.orgMaxOrgs = 2; World.prototype.getFreePos = () => {return {x: 399, y: 1}}; - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() @@ -371,7 +377,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 10000) {throw 'Error sending organism between Managers'} iterated1++; }); - man2.on(EVENTS.ITERATION, () => iterated2++); + man2.on(EVENTS.LOOP, () => iterated2++); waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); }); @@ -388,6 +394,7 @@ describe("client/src/manager/Manager", () => { const clone = OConfig.orgClonePeriod; const height = Config.worldHeight; const energy = OConfig.orgStartEnergy; + const max = OConfig.orgMaxOrgs; const server = new Server(); Config.worldHeight = 400; Config.worldWidth = 400; @@ -414,6 +421,7 @@ describe("client/src/manager/Manager", () => { OConfig.orgRainMutationPeriod = period; OConfig.orgStartAmount = amount; Config.worldHeight = height; + OConfig.orgMaxOrgs = max; done(); }); }); @@ -426,9 +434,10 @@ describe("client/src/manager/Manager", () => { OConfig.orgEnergySpendPeriod = 0; OConfig.orgClonePeriod = 0; OConfig.orgStartEnergy = 10000; + OConfig.orgMaxOrgs = 1; World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() @@ -452,7 +461,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 10000) {throw 'Error sending organism between Managers'} iterated1++; }); - man2.on(EVENTS.ITERATION, () => { + man2.on(EVENTS.LOOP, () => { !iterated2 && (org2 = man2.organisms.first.val); iterated2++; }); @@ -644,7 +653,7 @@ describe("client/src/manager/Manager", () => { cfg.set('worldCyclical', false); World.prototype.getFreePos = () => {return {x: 1, y: 9}}; - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; @@ -655,7 +664,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 10000) {throw 'Error sending organism between Servers'} iterated1++; }); - man2.on(EVENTS.ITERATION, () => iterated2++); + man2.on(EVENTS.LOOP, () => iterated2++); waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { @@ -723,7 +732,7 @@ describe("client/src/manager/Manager", () => { cfg.set('worldCyclical', false); World.prototype.getFreePos = () => {return {x: 0, y: 1}}; - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; @@ -738,7 +747,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 10000) {throw 'Error sending organism between Servers'} iterated1++; }); - man2.on(EVENTS.ITERATION, () => iterated2++); + man2.on(EVENTS.LOOP, () => iterated2++); waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { @@ -790,6 +799,7 @@ describe("client/src/manager/Manager", () => { cfg.set('serverHost', SERVER_HOST); const man1 = new Manager(false); ocfg.set('orgStartAmount', 1); + ocfg.set('orgMaxOrgs', 1); ocfg.set('orgRainMutationPeriod', 0); ocfg.set('orgCloneMutationPercent',0); ocfg.set('orgEnergySpendPeriod', 0); @@ -798,7 +808,7 @@ describe("client/src/manager/Manager", () => { cfg.set('worldCyclical', false); World.prototype.getFreePos = () => {return {x: 5, y: 1}}; - man1.on(EVENTS.ITERATION, () => { + man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && org1 === null) { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() @@ -860,7 +870,7 @@ describe("client/src/manager/Manager", () => { testQ(done, [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], [waitObj], - [man1, EVENTS.ITERATION, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001010000000000000000000000000)], // onStepRight() + [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001010000000000000000000000000)], // onStepRight() [man3, EVENTS.STEP_IN, () => {}, () => destroy()] ); }); From 96e8289cced5f5876624408b1b77115a8a6a121d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 10 Jan 2018 23:39:17 +0200 Subject: [PATCH 112/291] small speed optimizations --- .../manager/plugins/organisms/Organisms.js | 11 +++++--- .../plugins/organisms/dos/Organisms.js | 25 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index da8c954..50e5ddb 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -84,6 +84,9 @@ class Organisms extends Configurable { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; this.randOrgItem = this.organisms.first; + this.positions = manager.positions; + this.world = manager.world; + this._mutator = new Mutator(manager); this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -119,7 +122,7 @@ class Organisms extends Configurable { move(x1, y1, x2, y2, org) { let moved = false; - const world = this.parent.world; + const world = this.world; if (world.isFree(x2, y2) === false) {return false} if (x1 !== x2 || y1 !== y2) {moved = true; world.setDot(x1, y1, 0)} @@ -200,7 +203,7 @@ class Organisms extends Configurable { _clone(org) { if (this.onBeforeClone(org) === false) {return false} - let pos = this.parent.world.getNearFreePos(org.x, org.y); + let pos = this.world.getNearFreePos(org.x, org.y); if (pos === false || this.createOrg(pos, org) === false) {return false} let child = this.organisms.last.val; @@ -221,7 +224,7 @@ class Organisms extends Configurable { } _createPopulation() { - const world = this.parent.world; + const world = this.world; this.reset(); for (let i = 0, len = OConfig.orgStartAmount; i < len; i++) { @@ -250,7 +253,7 @@ class Organisms extends Configurable { } } this.organisms.del(org.item); - this.parent.world.setDot(org.x, org.y, 0); + this.world.setDot(org.x, org.y, 0); this.onAfterKillOrg(org); this.parent.fire(EVENTS.KILL_ORGANISM, org); //Console.info(org.id, ' die'); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index a75e742..555b7bc 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -102,11 +102,11 @@ class Organisms extends BaseOrganisms { * @override */ onAfterKillOrg(org) { - delete this.parent.positions[org.posId]; + delete this.positions[org.posId]; } /** - * Is called after moving of organism is done. Updates this.parent.positions + * Is called after moving of organism is done. Updates this.positions * map with a new position of organism * @param {Number} x1 Start X position * @param {Number} y1 Start Y position @@ -118,8 +118,8 @@ class Organisms extends BaseOrganisms { */ onAfterMove(x1, y1, x2, y2, org) { if (x1 !== x2 || y1 !== y2) { - delete this.parent.positions[Helper.posId(x1, y1)]; - this.parent.positions[Helper.posId(x2, y2)] = org; + delete this.positions[Helper.posId(x1, y1)]; + this.positions[Helper.posId(x2, y2)] = org; } return true; @@ -129,23 +129,22 @@ class Organisms extends BaseOrganisms { if (x < 0 || y < 0 || !Number.isInteger(x) || !Number.isInteger(y)) {return} const posId = Helper.posId(x, y); - if (typeof(this.parent.positions[posId]) === 'undefined') { - ret.ret = this.parent.world.getDot(x, y) + if (typeof(this.positions[posId]) === 'undefined') { + ret.ret = this.world.getDot(x, y) } else { - ret.ret = this.parent.positions[posId].energy; + ret.ret = this.positions[posId].energy; } } _onEat(org, x, y, ret) { - const world = this.parent.world; - const positions = this.parent.positions; + const positions = this.positions; let dir; [x, y, dir] = Helper.normalize(x, y); const posId = Helper.posId(x, y); if (typeof(positions[posId]) === 'undefined') { - ret.ret = world.grabDot(x, y, ret.ret); + ret.ret = this.world.grabDot(x, y, ret.ret); } else { ret.ret = ret.ret < 0 ? 0 : (ret.ret > positions[posId].energy ? positions[posId].energy : ret.ret); positions[posId].grabEnergy(ret.ret); @@ -211,7 +210,7 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.parent.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { + if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); // @@ -227,8 +226,8 @@ class Organisms extends BaseOrganisms { let dir; [x, y, dir] = Helper.normalize(x, y); - if (typeof(this.parent.positions[Helper.posId(x, y)]) === 'undefined') { - ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; + if (typeof(this.positions[Helper.posId(x, y)]) === 'undefined') { + ret.ret = this.world.getDot(x, y) > 0 ? ENERGY : EMPTY; } else { ret.ret = ORGANISM; } From dcab8af1960e79ec1f61e8873856b5189d8eb87b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 11 Jan 2018 00:06:26 +0200 Subject: [PATCH 113/291] fixed few tests #83 --- client/src/manager/plugins/client/ClientSpec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/manager/plugins/client/ClientSpec.js b/client/src/manager/plugins/client/ClientSpec.js index d0d121a..0bb9074 100644 --- a/client/src/manager/plugins/client/ClientSpec.js +++ b/client/src/manager/plugins/client/ClientSpec.js @@ -85,6 +85,7 @@ describe("client/src/manager/plugins/Client", () => { stop() {} get clientId() {return this._clientId} set clientId(id) {this._clientId = id} + resetActive() {} } const man = new Man0(); const client = new Client(man); @@ -105,6 +106,7 @@ describe("client/src/manager/plugins/Client", () => { stop() {} get clientId() {return this._clientId} set clientId(id) {this._clientId = id} + resetActive() {} } const man = new Man(); const server = new Server(SConfig.port); @@ -137,6 +139,7 @@ describe("client/src/manager/plugins/Client", () => { stop() {} get clientId() {return this._clientId} set clientId(id) {this._clientId = id; id && ++count === 2 && (waitObj.done = true)} + resetActive() {} } const man1 = new Man1(); const man2 = new Man1(); From ab8aa31d2eca008c26e99a83a91d52d7c7501e90 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 12 Jan 2018 00:51:30 +0200 Subject: [PATCH 114/291] added mechanism of random organisms creation and adding to the population to prevent stuck on local optimum --- client/src/manager/plugins/organisms/Config.js | 13 +++++++++---- client/src/manager/plugins/organisms/Organisms.js | 11 +++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 7c4e3d3..f6a118d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -71,7 +71,12 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 30, + orgTournamentPeriod: 110, + /** + * {Number} Period of iterations for creation of random organisms. Set it to 0 + * to turn off this feature + */ + orgRandomOrgPeriod: 400, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -149,7 +154,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 100, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -157,7 +162,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 64, + codeMaxSize: 80, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. @@ -189,7 +194,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 200, + codeIterationsPerOnce: 300, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 50e5ddb..1741ae9 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -183,6 +183,7 @@ class Organisms extends Configurable { this._updateAmount(counter); this._updateCrossover(counter); + this._updateRandomOrgs(counter); } _onLoop() { @@ -276,6 +277,16 @@ class Organisms extends Configurable { return true; } + _updateRandomOrgs(counter) { + const orgAmount = this.organisms.size; + if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgRandomOrgPeriod !== 0 && OConfig.orgRandomOrgPeriod === 0 || this.organisms.size < 1) {return false} + const size = this.randOrg().vm.size; + if (!this.createOrg(this.parent.world.getFreePos())) {return false} + const vm = this.organisms.last.val.vm; + + for (let i = 0; i < size; i++) {vm.insertLine()} + } + _updateCreate() { if (this.organisms.size < 1) { this._createPopulation(); From 451891cc93e9b88a1b549c39fec555b067b6565f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 12 Jan 2018 00:54:20 +0200 Subject: [PATCH 115/291] small refactoring --- client/src/manager/plugins/organisms/Organisms.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 1741ae9..4bbbe64 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -279,7 +279,7 @@ class Organisms extends Configurable { _updateRandomOrgs(counter) { const orgAmount = this.organisms.size; - if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgRandomOrgPeriod !== 0 && OConfig.orgRandomOrgPeriod === 0 || this.organisms.size < 1) {return false} + if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgRandomOrgPeriod !== 0 && OConfig.orgRandomOrgPeriod === 0 || orgAmount< 1) {return false} const size = this.randOrg().vm.size; if (!this.createOrg(this.parent.world.getFreePos())) {return false} const vm = this.organisms.last.val.vm; From 33264a7c31ebbc8e91509cd4c423a6ce1e5053fc Mon Sep 17 00:00:00 2001 From: tmptrash Date: Fri, 12 Jan 2018 19:38:41 +0200 Subject: [PATCH 116/291] in process of fixing more effective crossover and random organisms --- client/src/manager/plugins/organisms/Config.js | 10 +++++----- .../src/manager/plugins/organisms/Organisms.js | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index f6a118d..9c8fe84 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -64,19 +64,19 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 300, + orgCrossoverPeriod: 400, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 110, + orgTournamentPeriod: 500, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 400, + orgRandomOrgPeriod: 500, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -154,7 +154,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 100, + orgMaxOrgs: 200, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -179,7 +179,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 5, + codeYieldPeriod: 15, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 4bbbe64..d42c268 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -266,25 +266,33 @@ class Organisms extends Configurable { _updateCrossover(counter) { const orgAmount = this.organisms.size; - if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgCrossoverPeriod !== 0 && OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} + if (counter % OConfig.orgCrossoverPeriod !== 0 && OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} let org1 = this._tournament(); let org2 = this._tournament(); if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); + orgAmount > OConfig.orgMaxOrgs && this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); return true; } _updateRandomOrgs(counter) { const orgAmount = this.organisms.size; - if (orgAmount >= OConfig.orgMaxOrgs || counter % OConfig.orgRandomOrgPeriod !== 0 && OConfig.orgRandomOrgPeriod === 0 || orgAmount< 1) {return false} - const size = this.randOrg().vm.size; - if (!this.createOrg(this.parent.world.getFreePos())) {return false} + if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || orgAmount < 1 || !this.createOrg(this.parent.world.getFreePos())) {return false} + const org1 = this.randOrg(); + const size = org1.vm.size; const vm = this.organisms.last.val.vm; for (let i = 0; i < size; i++) {vm.insertLine()} + if (orgAmount > OConfig.orgMaxOrgs) { + const org2 = this.randOrg(); + if (!org1.alive || !org2.alive || org1 === org2) {return false} + this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); + } + + return true; } _updateCreate() { From aa5f053e5b9e2a6d9b61433e1ad37d9d60fec892 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 13 Jan 2018 00:42:04 +0200 Subject: [PATCH 117/291] fixed many small and critical issues in calculating values of Status plugin added an ability to put some energy on a field by organism fixed an issue of evolutionary stack (no mutations) fixed handling of zero value of config parameters default amount of changes from now - 0 --- client/src/manager/plugins/ips/Ips.js | 12 +++++------ .../src/manager/plugins/organisms/Config.js | 21 +++++++------------ .../src/manager/plugins/organisms/Mutator.js | 6 +++--- .../src/manager/plugins/organisms/Organism.js | 6 ++++-- .../manager/plugins/organisms/Organisms.js | 2 +- .../plugins/organisms/dos/Operators.js | 2 +- .../plugins/organisms/dos/Organisms.js | 7 ++++--- client/src/manager/plugins/status/Status.js | 18 ++++++++-------- client/src/share/Config.js | 4 ++-- 9 files changed, 38 insertions(+), 40 deletions(-) diff --git a/client/src/manager/plugins/ips/Ips.js b/client/src/manager/plugins/ips/Ips.js index 346626b..302a25e 100644 --- a/client/src/manager/plugins/ips/Ips.js +++ b/client/src/manager/plugins/ips/Ips.js @@ -19,19 +19,19 @@ const IpsConfig = require('./Config'); class Ips extends Configurable { constructor(manager) { super(manager, {Config, cfg: IpsConfig}, {show: ['_show', 'Shows IPS of the world']}); - this._stamp = Date.now(); - this._onIterationCb = this._onIteration.bind(this); + this._stamp = Date.now(); + this._onLoopCb = this._onLoop.bind(this); - Helper.override(manager, 'onIteration', this._onIterationCb); + Helper.override(manager, 'onLoop', this._onLoopCb); } destroy() { - Helper.unoverride(this.parent, 'onIteration', this._onIterationCb); - this._onIterationCb = null; + Helper.unoverride(this.parent, 'onLoop', this._onLoopCb); + this._onLoopCb = null; super.destroy(); } - _onIteration(counter, stamp) { + _onLoop(counter, stamp) { if (!this.cfg.show) {return} const ts = stamp - this._stamp; if (ts < this.cfg.periodMs) {return} diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 9c8fe84..35e1dba 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -4,11 +4,6 @@ * @author flatline */ const Config = { - /** - * {Number} Maximum value of mutation period in iterations. It's used - * in mutations of org.mutationPeriod parameter - */ - ORG_MAX_MUTATION_PERIOD: 10000, /** * {Number} Maximum amount of iterations for clone period */ @@ -21,7 +16,7 @@ const Config = { /** * {Number} Maximum color index of organism */ - ORG_MAX_COLOR: Number.MAX_SAFE_INTEGER, + ORG_MAX_COLOR: 0xFFFFFF, /** * {Number} Max value, which we may use in orgMutationProbs array. We may use * range: [0...ORG_MUTATION_PROBS_MAX_VAL] including these values @@ -55,7 +50,7 @@ const Config = { * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ - orgCloneMutationPercent: 0.0, + orgCloneMutationPercent: 0.1, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ @@ -64,19 +59,19 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 400, + orgCrossoverPeriod: 0, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 500, + orgTournamentPeriod: 0, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 500, + orgRandomOrgPeriod: 0, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -125,7 +120,7 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 6, + orgGarbagePeriod: 10, /** * {Number} Size of organism stack (internal memory) */ @@ -154,7 +149,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 300, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -179,7 +174,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 15, + codeYieldPeriod: 10, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 7781bf1..96b2773 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -70,7 +70,7 @@ class Mutator { } static _onPeriod(org) { - org.mutationPeriod = Helper.rand(OConfig.ORG_MAX_MUTATION_PERIOD); + org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod); org.changes++; } @@ -120,13 +120,13 @@ class Mutator { } _onOrganism(org) { - if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && org.mutationPeriod > 0 && org.alive) { + if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && OConfig.orgRainMutationPercent > 0.0 && org.mutationPeriod > 0 && org.alive) { this._mutate(org, false); } } _onCloneOrg(parent, child) { - if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0) {this._mutate(child)} + if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0.0 && OConfig.orgClonePeriod > 0) {this._mutate(child)} } /** diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 0f7ba2a..a81c852 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -86,7 +86,9 @@ class Organism extends Observer { set clonePeriod(p) {this._clonePeriod = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set energy(e) {this._energy = e} + set energy(e) { + this._energy = e; + } set changes(c) { this._changes = c; this._updateColor(c); @@ -206,7 +208,7 @@ class Organism extends Observer { this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; - this._changes = 1; + this._changes = 0; this._mem = []; } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index d42c268..261cf56 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -266,7 +266,7 @@ class Organisms extends Configurable { _updateCrossover(counter) { const orgAmount = this.organisms.size; - if (counter % OConfig.orgCrossoverPeriod !== 0 && OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} + if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} let org1 = this._tournament(); let org2 = this._tournament(); diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 6722f7c..b4d63d4 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -232,7 +232,7 @@ class OperatorsDos extends Operators { let ret = {ret: amount}; this.obs.fire(EVENTS.EAT, org, x, y, ret); - if (!IS_NUM(ret.ret)) {return 0} + if (!IS_NUM(ret.ret) || ret.ret === 0) {return 0} org.energy += ret.ret; return ret.ret; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 555b7bc..ba09011 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -138,16 +138,17 @@ class Organisms extends BaseOrganisms { _onEat(org, x, y, ret) { const positions = this.positions; + const eat = ret.ret; let dir; [x, y, dir] = Helper.normalize(x, y); const posId = Helper.posId(x, y); if (typeof(positions[posId]) === 'undefined') { - ret.ret = this.world.grabDot(x, y, ret.ret); + eat < 0 ? this.world.setDot(x, y, -eat) : (ret.ret = this.world.grabDot(x, y, eat)); } else { - ret.ret = ret.ret < 0 ? 0 : (ret.ret > positions[posId].energy ? positions[posId].energy : ret.ret); - positions[posId].grabEnergy(ret.ret); + ret.ret = eat < 0 ? 0 : (eat > positions[posId].energy ? positions[posId].energy : eat); + positions[posId].grabEnergy(eat); } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 36e8128..156ba7a 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -78,14 +78,14 @@ class Status extends Configurable { const format = Status._format; const orgAmount = orgs.size || 1; const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); - const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); - const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); - const sage = format(this._age / this._ageCount, 'age', orgAmount, 0, 11, 1 ); - const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); + const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); + const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); + const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); + const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); + const sage = format(this._age / (this._ageCount || 1), 'age', orgAmount, 0, 11, 1 ); + const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); const active = man.activeAround; @@ -106,7 +106,7 @@ class Status extends Configurable { _onBeforeLog(ips, orgs) { const olds = this._oldValues; const size = orgs.size || 1; - const lines = this._runLines; + const lines = this._runLines || 1; let energy = 0; let fitness = 0; let changes = 0; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index f49eea9..4806000 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -75,13 +75,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.1, + worldEnergyCheckPercent: 0.4, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 10000, + worldEnergyCheckPeriod: 5000, /** * {Boolean} Turns on/off scroll bars in a 2D canvas */ From 34ae0ad5e380c0e445e50d1be898f7028fbc66c8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 13 Jan 2018 01:12:27 +0200 Subject: [PATCH 118/291] fixed an issue of reaching code size maximum for organisms --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/vm/VM.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 35e1dba..be5e3fd 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -59,7 +59,7 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 100, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index d408d5b..c3592cb 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -175,7 +175,7 @@ class VM extends Observer { [start1, end1] = [end1, start1] } - adds = Math.abs(end1 - start1 - end + start); + adds = end1 - start1 - end + start; if (this._code.length + adds >= OConfig.codeMaxSize) { return 0 } From b4625c8c723afb475416160cce30c4a8d706f9e4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 13 Jan 2018 11:18:56 +0200 Subject: [PATCH 119/291] small fixes of mutations logic --- .../src/manager/plugins/organisms/Organisms.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index d42c268..6e65155 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -266,14 +266,14 @@ class Organisms extends Configurable { _updateCrossover(counter) { const orgAmount = this.organisms.size; - if (counter % OConfig.orgCrossoverPeriod !== 0 && OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} + if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} let org1 = this._tournament(); let org2 = this._tournament(); if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); - orgAmount > OConfig.orgMaxOrgs && this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); + (orgAmount + 1) > OConfig.orgMaxOrgs && org1.destroy(); return true; } @@ -281,16 +281,14 @@ class Organisms extends Configurable { _updateRandomOrgs(counter) { const orgAmount = this.organisms.size; if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || orgAmount < 1 || !this.createOrg(this.parent.world.getFreePos())) {return false} - const org1 = this.randOrg(); - const size = org1.vm.size; - const vm = this.organisms.last.val.vm; + const org = this.randOrg(); + const size = org.vm.size; + const newOrg = this.organisms.last.val; + const vm = newOrg.vm; + if (org === newOrg) {return false} for (let i = 0; i < size; i++) {vm.insertLine()} - if (orgAmount > OConfig.orgMaxOrgs) { - const org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2) {return false} - this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); - } + (orgAmount + 1) > OConfig.orgMaxOrgs && org.destroy(); return true; } From d02e317f88ac5ee3c1134229e84eb435411689da Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 13 Jan 2018 14:09:07 +0200 Subject: [PATCH 120/291] added panzoom library. from now scroll and zoom features for canvas are available optimized random organism code generation --- README.md | 2 +- .../src/manager/plugins/organisms/Config.js | 2 +- .../manager/plugins/organisms/Organisms.js | 7 +++---- client/src/manager/plugins/status/Status.js | 4 ++-- client/src/view/Canvas.js | 21 +++++++++++++++++++ client/src/vm/VM.js | 10 +++++++++ package.json | 1 + 7 files changed, 39 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 00aae1e..689382d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ - To run construct in a "serverless" mode, just open `./client/dist/index.html` in Chrome - To run construct in a "distributed" mode, you have to: - Choose some host in your local netwok for server - - Clone construct repo to this host + - Clone construct repo to this host - Go to configuration `./client/src/share/Config.js`, find `serverHost` option and change it to the IP, of your server host. You may use `ipconfig` under windows to get server's IP - Run `npm run build` command in a terminal from the root folder - Run server `npm run server` on chosen host diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index be5e3fd..5050aae 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -77,7 +77,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 300, + orgRainMutationPeriod: 0, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 6e65155..db79455 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -281,15 +281,14 @@ class Organisms extends Configurable { _updateRandomOrgs(counter) { const orgAmount = this.organisms.size; if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || orgAmount < 1 || !this.createOrg(this.parent.world.getFreePos())) {return false} - const org = this.randOrg(); - const size = org.vm.size; + const org = this.randOrg(); const newOrg = this.organisms.last.val; const vm = newOrg.vm; if (org === newOrg) {return false} - for (let i = 0; i < size; i++) {vm.insertLine()} + vm.generate(org.vm.size); (orgAmount + 1) > OConfig.orgMaxOrgs && org.destroy(); - + return true; } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 156ba7a..5c7943a 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -81,7 +81,7 @@ class Status extends Configurable { const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 12, 100000 ); + const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); const sage = format(this._age / (this._ageCount || 1), 'age', orgAmount, 0, 11, 1 ); @@ -94,7 +94,7 @@ class Status extends Configurable { } _onOrganism(org, lines) { - if (!StatusConfig.showMessages) {return} + if (!StatusConfig.showMessages) {return} this._runLines += lines; } diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 5e32b8a..3df88e4 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -3,6 +3,8 @@ * * @author flatline */ +const Panzoom = require('panzoom'); + class Canvas { constructor(width, height, noScrolls = false) { const id = 'world'; @@ -26,14 +28,18 @@ class Canvas { this._data = this._imgData.data; this._animate = this._onAnimate.bind(this); this._visualize = true; + this._panZoom = null; this._ctx.font = "18px Consolas"; this._ctx.fillStyle = "white"; + this._initPanZoomLib(); + this.clear(); window.requestAnimationFrame(this._animate); } destroy() { + this._panZoom.dispose(); this._canvasEl.parentNode.removeChild(this._canvasEl); this._ctx = null; this._imgData = null; @@ -110,6 +116,21 @@ class Canvas { htmlEl.style.height = '100%'; htmlEl.style.margin = 0; } + + /** + * Initializes 'panzoom' library, which adds possibility to + * zoom and scroll canvas by mouse. imageRendering css property + * removes smooth effect while zooming + */ + _initPanZoomLib() { + document.body.style.backgroundColor = '#9e9e9e'; + this._canvasEl.style.imageRendering = 'pixelated'; + this._panZoom = Panzoom(this._canvasEl, { + zoomSpeed : 0.1, + smoothScroll: false + }); + this._panZoom.zoomAbs(0, 0, 0.2); + } } module.exports = Canvas; \ No newline at end of file diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index c3592cb..cbe90ea 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -247,6 +247,16 @@ class VM extends Observer { return this._code[index]; } + /** + * Generates random code of organism with specified size + * @param {Number} size Final code size + */ + generate(size) { + const code = this._code = new Array(size); + + for (let i = 0; i < size; i++) {code[i] = Num.get()} + } + _reset() { this.fire(EVENTS.RESET_CODE); this._line = 0; diff --git a/package.json b/package.json index 6e553fe..d57ef03 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "babel-preset-env": "^1.6.0", "jasmine": "^2.6.0", "js-beautify": "^1.6.14", + "panzoom": "^4.1.0", "webpack": "^3.9.1", "ws": "^3.3.2" }, From 916df561143b7b1821375eb997a61302b4e5826e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 13 Jan 2018 16:39:54 +0200 Subject: [PATCH 121/291] default configuration for 'natural' mode fixed energy grabbing by the system formula --- .../src/manager/plugins/organisms/Config.js | 38 ++++++++-------- .../src/manager/plugins/organisms/Organism.js | 2 +- client/src/view/Canvas.js | 44 +++++++++---------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5050aae..9f94c7f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -59,14 +59,14 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 100, + orgCrossoverPeriod: 0, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 0, + orgTournamentPeriod: 100, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature @@ -82,22 +82,7 @@ const Config = { * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.2, - /** - * {Number} Amount of organisms we have to create on program start - */ - orgStartAmount: 300, - /** - * {Number} Amount of energy for first organisms. They are like Adam and - * Eve. It means that these empty (without vm) organism were created - * by operator and not by evolution. - */ - orgStartEnergy: 50000, - /** - * {Number} Begin color of "empty" organism (organism without code). Color - * should be set in HEX-RGB mode. Example: 0xRRGGBB - */ - orgStartColor: 0xFF0000, + orgRainMutationPercent: 0.0, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -149,7 +134,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 3000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -158,6 +143,21 @@ const Config = { * effective mechanisms of energy obtaining. */ codeMaxSize: 80, + /** + * {Number} Amount of organisms we have to create on program start + */ + orgStartAmount: 300, + /** + * {Number} Amount of energy for first organisms. They are like Adam and + * Eve. It means that these empty (without vm) organism were created + * by operator and not by evolution. + */ + orgStartEnergy: 50000, + /** + * {Number} Begin color of "empty" organism (organism without code). Color + * should be set in HEX-RGB mode. Example: 0xRRGGBB + */ + orgStartColor: 0xFF0000, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index a81c852..ed60e48 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -252,7 +252,7 @@ class Organism extends Observer { */ _updateEnergy() { if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - let grabSize = Math.floor(this.vm.size / OConfig.orgGarbagePeriod); + let grabSize = Math.round(this.vm.size / OConfig.orgGarbagePeriod); if (grabSize < 1) {grabSize = 1} return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 3df88e4..2e2f264 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -7,16 +7,10 @@ const Panzoom = require('panzoom'); class Canvas { constructor(width, height, noScrolls = false) { - const id = 'world'; - const doc = document; - const bodyEl = doc.body; + const id = 'world'; + const doc = document; - this._prepareDom(); - bodyEl.innerHTML += ``; - // - // This style hides scroll bars on full screen 2d canvas - // - if (noScrolls) {document.querySelector('html').style.overflow = 'hidden'} + doc.body.innerHTML += ``; this._id = id; this._width = width; @@ -30,10 +24,8 @@ class Canvas { this._visualize = true; this._panZoom = null; - this._ctx.font = "18px Consolas"; - this._ctx.fillStyle = "white"; + this._prepareDom(noScrolls); this._initPanZoomLib(); - this.clear(); window.requestAnimationFrame(this._animate); } @@ -105,16 +97,25 @@ class Canvas { } } - _prepareDom() { - const bodyEl = document.querySelector('body'); + _prepareDom(noScrolls) { + const bodyEl = document.body; const htmlEl = document.querySelector('html'); - bodyEl.style.width = '100%'; - bodyEl.style.height = '100%'; - bodyEl.style.margin = 0; - htmlEl.style.width = '100%'; - htmlEl.style.height = '100%'; - htmlEl.style.margin = 0; + bodyEl.style.width = '100%'; + bodyEl.style.height = '100%'; + bodyEl.style.margin = 0; + bodyEl.style.backgroundColor = '#9e9e9e'; + + htmlEl.style.width = '100%'; + htmlEl.style.height = '100%'; + htmlEl.style.margin = 0; + + this._ctx.font = "18px Consolas"; + this._ctx.fillStyle = "white"; + // + // This style hides scroll bars on full screen 2d canvas + // + if (noScrolls) {document.querySelector('html').style.overflow = 'hidden'} } /** @@ -123,13 +124,12 @@ class Canvas { * removes smooth effect while zooming */ _initPanZoomLib() { - document.body.style.backgroundColor = '#9e9e9e'; this._canvasEl.style.imageRendering = 'pixelated'; this._panZoom = Panzoom(this._canvasEl, { zoomSpeed : 0.1, smoothScroll: false }); - this._panZoom.zoomAbs(0, 0, 0.2); + this._panZoom.zoomAbs(0, 0, 0.5); } } From fd9f4bcb237464717dd7a997cbad9135acae16a4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 14 Jan 2018 02:06:41 +0200 Subject: [PATCH 122/291] added Charts plugin with two worked charts at the moment: IPS and Energy #15 refactored Status plugin as a base class (data collector) for Charts and Console plugins optimized index.html (removed extra tags) added google-charts npm dependency --- client/dist/index.html | 21 ++- .../src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/status/Status.js | 120 +++++++++--------- .../manager/plugins/status/charts/Chart.js | 114 +++++++++++++++++ .../manager/plugins/status/charts/Charts.js | 113 +++++++++++++++++ .../manager/plugins/status/charts/Config.js | 24 ++++ .../plugins/status/{ => console}/Config.js | 6 +- .../manager/plugins/status/console/Console.js | 68 ++++++++++ client/src/share/Config.js | 3 +- package.json | 1 + 10 files changed, 393 insertions(+), 79 deletions(-) create mode 100644 client/src/manager/plugins/status/charts/Chart.js create mode 100644 client/src/manager/plugins/status/charts/Charts.js create mode 100644 client/src/manager/plugins/status/charts/Config.js rename client/src/manager/plugins/status/{ => console}/Config.js (64%) create mode 100644 client/src/manager/plugins/status/console/Console.js diff --git a/client/dist/index.html b/client/dist/index.html index 7aa278c..0dad7b7 100644 --- a/client/dist/index.html +++ b/client/dist/index.html @@ -1,15 +1,10 @@ - - - - - - - construct - - - - - + + + construct - digital organisms simulator + + + + + \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 9f94c7f..683cd8f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -189,7 +189,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 300, + codeIterationsPerOnce: 200, }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 5c7943a..bed3747 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -1,8 +1,8 @@ /** - * This plugin is a primitive version of real time charts. It shows - * different parameters of the jevo.js system, like average energy, - * iq (energy picking speed), average code size and so on. Here - * labels explanation: + * Base class for plugin which collects real time data about system like: + * population energy, changes, organisms iq etc and provide this data to + * other visualization classes (e.g. Charts). Output data is an object of + * described below format: * * ips: Iterations Per Second - amount of all organisms full * code runs per one second @@ -17,24 +17,23 @@ * * @author flatline */ -const Configurable = require('./../../../../../common/src/Configurable'); const EVENTS = require('./../../../share/Events').EVENTS; +const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; -const StatusConfig = require('./Config'); - -const GREEN = 'color: #00aa00'; -const RED = 'color: #aa0000'; class Status extends Configurable { - static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = false) { - const val = (value / (perOrg ? orgs : 1)) * coef; - return `${name}:${val.toFixed(fixed === -1 && 2 || (val < 10 && val > -10 ? fixed : 0))}`.padEnd(pad); - } - - constructor(manager) { - super(manager, {Config, cfg: StatusConfig}); - - this._manager = manager; + /** + * Is called every time, when new status data is available + * @param {Object} status Status data + * @param {Number} orgs Amount of organisms + * @abstract + */ + onStatus(status, orgs) {} + + constructor(manager, statCfg, apiCfg = {}) { + super(manager, {Config, cfg: statCfg}, apiCfg); + + this.manager = manager; this._stamp = 0; this._curEnergy = 0; this._energy = 0; @@ -46,6 +45,8 @@ class Status extends Configurable { this._ageCount = 0; this._times = 0; this._oldValues = [0, 0, 0]; + this._status = {ips:0, lps:0, orgs:0, energy:0, iq:0, changes:0, fit:0, age:0, code:0}; + this._statusCfg = statCfg; this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); @@ -56,54 +57,17 @@ class Status extends Configurable { } destroy() { - this._manager.off(EVENTS.KILL_ORGANISM, this._onKillOrgCb); - this._manager.off(EVENTS.ORGANISM, this._onOrganismCb); - this._manager.off(EVENTS.IPS, this._onIpsCb); + this.manager.off(EVENTS.KILL_ORGANISM, this._onKillOrgCb); + this.manager.off(EVENTS.ORGANISM, this._onOrganismCb); + this.manager.off(EVENTS.IPS, this._onIpsCb); this._onKillOrgCb = null; this._onOrganismCb = null; this._onIpsCb = null; - this._manager = null; + this.manager = null; this._oldValues = null; - super.destroy(); - } - - _onIps(ips, orgs) { - if (!StatusConfig.showMessages) {return} - const stamp = Date.now(); - this._times++; - if (stamp - this._stamp < StatusConfig.period) {return} - - const man = this._manager; - this._onBeforeLog(ips, orgs); - const format = Status._format; - const orgAmount = orgs.size || 1; - const sips = `ips:${ips.toFixed(ips < 10 ? 2 : 0)}`.padEnd(10); - const slps = format(this._runLines / this._times, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgAmount, 'org', orgAmount, 0, 10 ); - const senergy = format(this._curEnergy, 'nrg', orgAmount, 0, 14 ); - const siq = format(this._energy, 'iq', orgAmount, 3, 14, 100000 ); - const schanges = format(this._changes, 'che', orgAmount, 2, 12 ); - const sfit = format(this._fitness, 'fit', orgAmount, 2, 13 ); - const sage = format(this._age / (this._ageCount || 1), 'age', orgAmount, 0, 11, 1 ); - const scode = format(this._codeSize, 'cod', orgAmount, -1, 12, 1, true); - - console.log(`%c${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); - const active = man.activeAround; - man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); - this._onAfterLog(stamp); - } - - _onOrganism(org, lines) { - if (!StatusConfig.showMessages) {return} - this._runLines += lines; - } - - _onKillOrg(org) { - this._age += org.iterations; - this._ageCount++; } - _onBeforeLog(ips, orgs) { + onBeforeStatus(ips, orgs) { const olds = this._oldValues; const size = orgs.size || 1; const lines = this._runLines || 1; @@ -132,13 +96,47 @@ class Status extends Configurable { this._oldValues = [energy, changes, fitness]; } - _onAfterLog(stamp) { + onAfterStatus(stamp) { this._times = 0; this._runLines = 0; this._age = 0; this._ageCount = 0; this._stamp = stamp; } + + _onIps(ips, orgs) { + if (!this._statusCfg.active) {return} + this._times++; + const stamp = Date.now(); + if (stamp - this._stamp < this._statusCfg.period) {return} + const status = this._status; + + this.onBeforeStatus(ips, orgs); + + status.ips = +ips.toFixed(ips < 10 ? 2 : 0); + status.lps = this._runLines / this._times; + status.orgs = orgs.size; + status.energy = this._curEnergy; + status.iq = this._energy; + status.changes = this._changes; + status.fit = this._fitness; + status.age = this._age / (this._ageCount || 1); + status.code = this._codeSize; + + this.onStatus(status, orgs.size); + this.onAfterStatus(stamp); + } + + _onOrganism(org, lines) { + if (!this._statusCfg.active) {return} + this._runLines += lines; + } + + _onKillOrg(org) { + if (!this._statusCfg.active) {return} + this._age += org.iterations; + this._ageCount++; + } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js new file mode 100644 index 0000000..e1959fd --- /dev/null +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -0,0 +1,114 @@ +/** + * Draws one line chart using Google charts library. The purpose of + * this class is to show dynamics of changing for some property. For + * example: energy, iq or code size. update() method should obtain + * new portion of property data to draw on chart. Works only in browser. + * + * @author flatline + */ +const GoogleCharts = require('google-charts').GoogleCharts; + +class Chart { + constructor(title, cfg) { + this._options = { + title : title, + hAxis : {textStyle: {fontSize: 12}}, + vAxis : {textStyle: {fontSize: 12}}, + legend : 'none', + chartArea: {left: 100, top: 50, bottom: 60, width: '100%', height: '100%'}, + }; + this._data = null; + this._chart = null; + this._ready = false; + this._el = null; + this._cfg = cfg; + + GoogleCharts.load(cfg.active ? this._onReady.bind(this) : () => {}, 'corechart'); + } + + /** + * Updates chart with new portion of data + * @param {Array} data Array of two new values + * @return {Boolean} + */ + update(data) { + if (!this._ready || !this._cfg.active) {return false} + + this._data.addRow(data); + this._chart.draw(this._data, this._options); + + return true; + } + + set transparent(t) {this._el.style.opacity = t} + set pos(p) {this._updatePos(p)} + set active(a) {this._cfg.active !== a && this._updateActive(a)} + + destroy() { + this._cfg.active && this._chart.clearChart(); + this._el.parentNode.removeChild(this._el); + this._el = null; + this._data = null; + this._chart = null; + this._options = null; + } + + _onReady() { + const el = this._el = document.createElement("DIV"); + + el.style.position = 'absolute'; + el.style.opacity = this._cfg.transparent; + this._updatePos(this._cfg.pos); + document.body.appendChild(el); + + this._data = new google.visualization.DataTable(); + this._chart = new google.visualization.LineChart(el); + this._ready = true; + + this._data.addColumn('string', 'horizontal'); + this._data.addColumn('number', 'vertical'); + } + + /** + * Returns chart container sizes depending on position. Sizes format: + * [width, height, left, top] + * @param {String} pos Position + * @returns {Array} [width, height, left, top] + * @private + */ + _getSize(pos) { + return { + top : ['100%', '50%', '0', '0' ], + down : ['100%', '50%', '0', '50%'], + left : ['50%', '100%', '0', '0' ], + right : ['50%', '100%', '50%', '0' ], + topleft : ['50%', '50%', '0', '0' ], + downleft : ['50%', '50%', '0', '50%'], + topright : ['50%', '50%', '50%', '0' ], + downright: ['50%', '50%', '50%', '50%'], + full : ['100%', '100%', '0', '0' ] + }[pos]; + } + + _updatePos(pos) { + const style = this._el.style; + const size = this._getSize(pos); + + style.width = size[0]; + style.height = size[1]; + style.left = size[2]; + style.top = size[3]; + } + + _updateActive(active) { + if (active) { + this._onReady(); + } else { + this._chart.clearChart(); + this._el.parentNode.removeChild(this._el); + this._data = this._chart = null; + } + } +} + +module.exports = Chart; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js new file mode 100644 index 0000000..4ace686 --- /dev/null +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -0,0 +1,113 @@ +/** + * Manager plugin, which draws real time charts based on real time data. For example: + * energy, iq, changes and so on. The same values like Status plugin uses. + * + * @author flatline + */ +const Status = require('./../Status'); +const Chart = require('./Chart'); +const Config = require('./Config'); +const _each = require('lodash/each'); + +const API = { + transparent: ['_transparent', 'Sets transparent level' ], + pos : ['_pos', 'Sets chart position' ], + active : ['_active', 'Activates/Deactivates chart'] +}; + +class Charts extends Status { + constructor(manager) { + super(manager, Config, API); + + this._data = new Array(2); + this._charts = { + ips : new Chart('IPS', Config.charts.ips), + energy: new Chart('Organism average energy', Config.charts.energy) + }; + } + + destroy() { + _each(this._charts, chart => chart.destroy()); + this._charts = null; + this._data = null; + + super.destroy(); + } + + /** + * Is called every time, when new status data is available + * @param {Object} status Status data + * @param {Number} orgs Amount of organisms + * @override + */ + onStatus(status, orgs) { + // const man = this.manager; + // const active = man.activeAround; + // const format = Console._format; + const stamp = Date.now(); + const time = new Date(stamp); + // + // const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; + // const conns = `con:${con === ' ' ? 'no ' : con}`; + const orgAmount = orgs || 1; + // const sips = `ips:${status.ips}`.padEnd(10); + // const slps = format(status.lps, 'lps', orgAmount, 0, 14 ); + // const sorgs = format(orgs, 'org', orgAmount, 0, 10 ); + // const senergy = format(status.energy, 'nrg', orgAmount, 0, 14 ); + // const siq = format(status.iq, 'iq', orgAmount, 3, 14, 100000 ); + // const schanges = format(status.changes, 'che', orgAmount, 2, 12 ); + // const sfit = format(status.fit, 'fit', orgAmount, 2, 13 ); + // const sage = format(status.age, 'age', orgAmount, 0, 11, 1 ); + // const scode = format(status.code, 'cod', orgAmount, -1, 12, 1, true); + + //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + // TODO: this code should be moved to separate plugin + //const active = man.activeAround; + //man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); + + + const data = this._data; + data[0] = `${time.getHours()}:${time.getMinutes()}`; + + data[1] = status.ips; + this._charts.ips.update(data); + + data[1] = status.energy; + this._charts.energy.update(data); + } + + /** + * Sets current chart transparent coefficient + * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {Number} t Value between 0...1 + * @api + */ + _transparent(chart, t) {this._setProperty(chart, 'transparent', t)} + + /** + * Sets current chart position. Available positions: + * top, down, left, right, topleft, downleft, topright, + * downright, full. + * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {String} p new position + * @api + */ + _pos(chart, p) {this._setProperty(chart, 'pos', p)} + + /** + * Sets current chart position. Available positions: + * top, down, left, right, topleft, downleft, topright, + * downright, full. + * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {Boolean} a New active state + * @api + */ + _active(chart, a) {this._setProperty(chart, 'active', a)} + + _setProperty(chart, prop, val) { + _each(this._charts, chart => chart[prop] = val); + this.cfg.charts[chart][prop] = val; + } +} + +module.exports = Charts; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js new file mode 100644 index 0000000..8d3e72f --- /dev/null +++ b/client/src/manager/plugins/status/charts/Config.js @@ -0,0 +1,24 @@ +/** + * Configuration of Status plugin + * + * @author flatline + */ +const Config = { + /** + * {Boolean} Turns on/off plugin data collection + */ + active: true, + /** + * {Number} Delay in milliseconds between showing one status line + */ + period: 2000, + /** + * {Object} Available chart types + */ + charts: { + ips : {pos: 'topleft', active: false, transparent: 0.5}, + energy: {pos: 'downleft', active: false, transparent: 0.5} + } +}; + +module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/status/Config.js b/client/src/manager/plugins/status/console/Config.js similarity index 64% rename from client/src/manager/plugins/status/Config.js rename to client/src/manager/plugins/status/console/Config.js index e64416d..f07246f 100644 --- a/client/src/manager/plugins/status/Config.js +++ b/client/src/manager/plugins/status/console/Config.js @@ -1,13 +1,13 @@ /** - * Configuration of Status plugin + * Configuration of Console plugin * * @author flatline */ const Config = { /** - * {Boolean} Shows/Hides messages in a console + * {Boolean} Turns on/off plugin data collection */ - showMessages: true, + active: true, /** * {Number} Delay in milliseconds between showing one status line */ diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js new file mode 100644 index 0000000..f1fbd28 --- /dev/null +++ b/client/src/manager/plugins/status/console/Console.js @@ -0,0 +1,68 @@ +/** + * This plugin is a primitive version of real time charts. It shows + * different parameters of the jevo.js system, like average energy, + * iq (energy picking speed), average code size and so on. Here + * labels explanation: + * + * ips: Iterations Per Second - amount of all organisms full + * code runs per one second + * lps: Lines Per Second - average amount of run code lines + * per one second + * org: Average amount of organisms at the moment of logging + * nrg: Amount of energy of average organism + * iq : Energy picking speed per StatusConfig.period seconds + * che: Changes amount of average organism + * fit: Fitness of average organism + * cod: Code size of average organism + * + * @author flatline + */ +const Status = require('./../Status'); +const Config = require('./Config'); + +const GREEN = 'color: #00aa00'; +const RED = 'color: #aa0000'; + +class Console extends Status { + static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = false) { + const val = (value / (perOrg ? orgs : 1)) * coef; + return `${name}:${val.toFixed(fixed === -1 && 2 || (val < 10 && val > -10 ? fixed : 0))}`.padEnd(pad); + } + + constructor(manager) { + super(manager, Config); + } + + destroy() { + super.destroy(); + } + + /** + * Is called every time, when new status data is available + * @param {Object} status Status data + * @param {Number} orgs Amount of organisms + * @override + */ + onStatus(status, orgs) { + const man = this.manager; + const active = man.activeAround; + const format = Console._format; + + const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; + const conns = `con:${con === ' ' ? 'no ' : con}`; + const orgAmount = orgs || 1; + const sips = `ips:${status.ips}`.padEnd(10); + const slps = format(status.lps, 'lps', orgAmount, 0, 14 ); + const sorgs = format(orgs, 'org', orgAmount, 0, 10 ); + const senergy = format(status.energy, 'nrg', orgAmount, 0, 14 ); + const siq = format(status.iq, 'iq', orgAmount, 3, 14, 100000 ); + const schanges = format(status.changes, 'che', orgAmount, 2, 12 ); + const sfit = format(status.fit, 'fit', orgAmount, 2, 13 ); + const sage = format(status.age, 'age', orgAmount, 0, 11, 1 ); + const scode = format(status.code, 'cod', orgAmount, -1, 12, 1, true); + + console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + } +} + +module.exports = Console; \ No newline at end of file diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 4806000..c78e429 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -32,7 +32,8 @@ ClientConfig.init({ 'Config', 'client/Client', 'Energy', - 'status/Status', + 'status/console/Console', + 'status/charts/Charts', 'ips/Ips', 'backup/Backup' ], diff --git a/package.json b/package.json index d57ef03..ea56373 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dependencies": { "babel-cli": "^6.24.1", "babel-preset-env": "^1.6.0", + "google-charts": "^1.0.0", "jasmine": "^2.6.0", "js-beautify": "^1.6.14", "panzoom": "^4.1.0", From fb7514385626775c522e1043ae1eb99cec3b9fbb Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 14 Jan 2018 02:20:56 +0200 Subject: [PATCH 123/291] fixed an issue with many commands in console for Charts plugin #15 --- client/src/manager/plugins/status/charts/Chart.js | 2 +- client/src/manager/plugins/status/charts/Charts.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index e1959fd..c0a1c2b 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -106,7 +106,7 @@ class Chart { } else { this._chart.clearChart(); this._el.parentNode.removeChild(this._el); - this._data = this._chart = null; + this._data = this._chart = this._el = null; } } } diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 4ace686..ae85758 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -105,7 +105,7 @@ class Charts extends Status { _active(chart, a) {this._setProperty(chart, 'active', a)} _setProperty(chart, prop, val) { - _each(this._charts, chart => chart[prop] = val); + this._charts[chart][prop] = val; this.cfg.charts[chart][prop] = val; } } From 9739725681b88420bc8e9977032857f13e30723c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 14 Jan 2018 14:14:02 +0200 Subject: [PATCH 124/291] added all 9 charts #15 fixed few issues with charts API (man.api.charts.xxx) --- client/src/manager/plugins/status/Status.js | 27 +++++++----- .../manager/plugins/status/charts/Chart.js | 2 + .../manager/plugins/status/charts/Charts.js | 41 ++++++++----------- .../manager/plugins/status/charts/Config.js | 12 +++++- .../manager/plugins/status/console/Console.js | 25 +++++------ client/src/view/Canvas.js | 2 +- 6 files changed, 56 insertions(+), 53 deletions(-) diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index bed3747..5656824 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -107,21 +107,22 @@ class Status extends Configurable { _onIps(ips, orgs) { if (!this._statusCfg.active) {return} this._times++; - const stamp = Date.now(); + const stamp = Date.now(); if (stamp - this._stamp < this._statusCfg.period) {return} - const status = this._status; + const status = this._status; + const orgAmount = orgs.size || 1; this.onBeforeStatus(ips, orgs); - status.ips = +ips.toFixed(ips < 10 ? 2 : 0); - status.lps = this._runLines / this._times; - status.orgs = orgs.size; - status.energy = this._curEnergy; - status.iq = this._energy; - status.changes = this._changes; - status.fit = this._fitness; - status.age = this._age / (this._ageCount || 1); - status.code = this._codeSize; + status.ips = this._toFixed(ips, 2); + status.lps = this._toFixed(this._runLines / this._times, 0); + status.orgs = orgAmount; + status.energy = this._toFixed(this._curEnergy, 2); + status.iq = this._toFixed(this._energy * 100000, 3); + status.changes = this._toFixed(this._changes, 2); + status.fit = this._toFixed(this._fitness, 2); + status.age = this._toFixed(this._age / (this._ageCount || 1), 2); + status.code = +(this._codeSize / orgAmount).toFixed(2); this.onStatus(status, orgs.size); this.onAfterStatus(stamp); @@ -137,6 +138,10 @@ class Status extends Configurable { this._age += org.iterations; this._ageCount++; } + + _toFixed(val, fixed) { + return +val.toFixed(val < 10 && val > -10 ? fixed : 0); + } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index c0a1c2b..b7ad82b 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -3,6 +3,7 @@ * this class is to show dynamics of changing for some property. For * example: energy, iq or code size. update() method should obtain * new portion of property data to draw on chart. Works only in browser. + * Requires internet connection for google charts dynamic load. * * @author flatline */ @@ -91,6 +92,7 @@ class Chart { } _updatePos(pos) { + if (!this._el) {return} const style = this._el.style; const size = this._getSize(pos); diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index ae85758..b8ec446 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -21,8 +21,15 @@ class Charts extends Status { this._data = new Array(2); this._charts = { - ips : new Chart('IPS', Config.charts.ips), - energy: new Chart('Organism average energy', Config.charts.energy) + ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), + lps : new Chart('LPS - Lines Per Second', Config.charts.lps), + orgs : new Chart('Amount of organisms', Config.charts.orgs), + energy : new Chart('Average organism energy', Config.charts.energy), + iq : new Chart('Average organism IQ (Energy pick speed)', Config.charts.iq), + changes: new Chart('Average organism changes (Mutations)', Config.charts.changes), + fit : new Chart('Average organism Fitness', Config.charts.fit), + age : new Chart('Average organism Age', Config.charts.age), + code : new Chart('Average organism code size', Config.charts.code) }; } @@ -41,24 +48,8 @@ class Charts extends Status { * @override */ onStatus(status, orgs) { - // const man = this.manager; - // const active = man.activeAround; - // const format = Console._format; const stamp = Date.now(); const time = new Date(stamp); - // - // const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; - // const conns = `con:${con === ' ' ? 'no ' : con}`; - const orgAmount = orgs || 1; - // const sips = `ips:${status.ips}`.padEnd(10); - // const slps = format(status.lps, 'lps', orgAmount, 0, 14 ); - // const sorgs = format(orgs, 'org', orgAmount, 0, 10 ); - // const senergy = format(status.energy, 'nrg', orgAmount, 0, 14 ); - // const siq = format(status.iq, 'iq', orgAmount, 3, 14, 100000 ); - // const schanges = format(status.changes, 'che', orgAmount, 2, 12 ); - // const sfit = format(status.fit, 'fit', orgAmount, 2, 13 ); - // const sage = format(status.age, 'age', orgAmount, 0, 11, 1 ); - // const scode = format(status.code, 'cod', orgAmount, -1, 12, 1, true); //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); // TODO: this code should be moved to separate plugin @@ -66,14 +57,14 @@ class Charts extends Status { //man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); - const data = this._data; - data[0] = `${time.getHours()}:${time.getMinutes()}`; + const data = this._data; + const charts = this._charts; + data[0] = `${time.getHours()}:${time.getMinutes()}`; - data[1] = status.ips; - this._charts.ips.update(data); - - data[1] = status.energy; - this._charts.energy.update(data); + _each(charts, (chart, key) => { + data[1] = status[key]; + chart.update(data); + }); } /** diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 8d3e72f..07721d1 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -16,8 +16,16 @@ const Config = { * {Object} Available chart types */ charts: { - ips : {pos: 'topleft', active: false, transparent: 0.5}, - energy: {pos: 'downleft', active: false, transparent: 0.5} + ips : {pos: 'topleft', active: false, transparent: 0.6}, + lps : {pos: 'downleft', active: false, transparent: 0.6}, + orgs : {pos: 'topright', active: false, transparent: 0.6}, + energy : {pos: 'downright', active: true, transparent: 0.6}, + iq : {pos: 'topleft', active: true, transparent: 0.6}, + changes: {pos: 'downleft', active: false, transparent: 0.6}, + fit : {pos: 'topright', active: true, transparent: 0.6}, + age : {pos: 'downright', active: false, transparent: 0.6}, + code : {pos: 'downleft', active: true, transparent: 0.6} + } }; diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index f1fbd28..4163e38 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -24,10 +24,7 @@ const GREEN = 'color: #00aa00'; const RED = 'color: #aa0000'; class Console extends Status { - static _format(value, name, orgs, fixed, pad, coef = 1, perOrg = false) { - const val = (value / (perOrg ? orgs : 1)) * coef; - return `${name}:${val.toFixed(fixed === -1 && 2 || (val < 10 && val > -10 ? fixed : 0))}`.padEnd(pad); - } + static _format(value, name, pad) {return `${name}:${value}`.padEnd(pad)} constructor(manager) { super(manager, Config); @@ -50,17 +47,17 @@ class Console extends Status { const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; const conns = `con:${con === ' ' ? 'no ' : con}`; - const orgAmount = orgs || 1; - const sips = `ips:${status.ips}`.padEnd(10); - const slps = format(status.lps, 'lps', orgAmount, 0, 14 ); - const sorgs = format(orgs, 'org', orgAmount, 0, 10 ); - const senergy = format(status.energy, 'nrg', orgAmount, 0, 14 ); - const siq = format(status.iq, 'iq', orgAmount, 3, 14, 100000 ); - const schanges = format(status.changes, 'che', orgAmount, 2, 12 ); - const sfit = format(status.fit, 'fit', orgAmount, 2, 13 ); - const sage = format(status.age, 'age', orgAmount, 0, 11, 1 ); - const scode = format(status.code, 'cod', orgAmount, -1, 12, 1, true); + const sips = format(status.ips, 'ips', 10); + const slps = format(status.lps, 'lps', 14); + const sorgs = format(orgs, 'org', 10); + const senergy = format(status.energy, 'nrg', 14); + const siq = format(status.iq, 'iq', 14); + const schanges = format(status.changes, 'che', 12); + const sfit = format(status.fit, 'fit', 13); + const sage = format(status.age, 'age', 11); + const scode = format(status.code, 'cod', 12); + // TODO: under Node.js should use Server/Console.xxx() console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 2e2f264..dad3606 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -129,7 +129,7 @@ class Canvas { zoomSpeed : 0.1, smoothScroll: false }); - this._panZoom.zoomAbs(0, 0, 0.5); + this._panZoom.zoomAbs(0, 0, 1.0); } } From 0c406596e4658c1d3391c21f42217cb9c5b993e6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 15 Jan 2018 00:18:12 +0200 Subject: [PATCH 125/291] fixed speed of set/delete property of Manager.positions object (map) #33 changed back Organism.changes logic. affects Organism.fitness() removed peak on charts at the very beginning --- .../src/manager/plugins/organisms/Organism.js | 5 ++- .../plugins/organisms/dos/Organisms.js | 4 +-- client/src/manager/plugins/status/Status.js | 31 +++++++++++-------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index ed60e48..4ff8537 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -56,6 +56,7 @@ class Organism extends Observer { this._x = x; this._y = y; this._iterations = 0; + this._changes = 0; this._alive = alive; this._item = item; this._fnId = 0; @@ -180,7 +181,7 @@ class Organism extends Observer { } fitness() { - return (OConfig.codeMaxSize - this.vm.size) * this._energy * this._changes; + return (OConfig.codeMaxSize - this.vm.size) * this._energy * (this._changes || 1); } destroy() { @@ -208,7 +209,6 @@ class Organism extends Observer { this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; - this._changes = 0; this._mem = []; } @@ -222,7 +222,6 @@ class Organism extends Observer { this._clonePeriod = parent.clonePeriod; this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; - this._changes = parent.changes; this._mem = parent.mem.slice(); } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index ba09011..5bb9e74 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -102,7 +102,7 @@ class Organisms extends BaseOrganisms { * @override */ onAfterKillOrg(org) { - delete this.positions[org.posId]; + this.positions[org.posId] = undefined; } /** @@ -118,7 +118,7 @@ class Organisms extends BaseOrganisms { */ onAfterMove(x1, y1, x2, y2, org) { if (x1 !== x2 || y1 !== y2) { - delete this.positions[Helper.posId(x1, y1)]; + this.positions[Helper.posId(x1, y1)] = undefined; this.positions[Helper.posId(x2, y2)] = org; } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 5656824..6f99cbf 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -10,7 +10,7 @@ * per one second * org: Average amount of organisms at the moment of logging * nrg: Amount of energy of average organism - * iq : Energy picking speed per StatusConfig.period seconds + * iq : Energy picking speed per status period * che: Changes amount of average organism * fit: Fitness of average organism * cod: Code size of average organism @@ -22,6 +22,10 @@ const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; class Status extends Configurable { + static _toFixed(val, fixed) { + return +val.toFixed(val < 10 && val > -10 ? fixed : 0); + } + /** * Is called every time, when new status data is available * @param {Object} status Status data @@ -47,6 +51,7 @@ class Status extends Configurable { this._oldValues = [0, 0, 0]; this._status = {ips:0, lps:0, orgs:0, energy:0, iq:0, changes:0, fit:0, age:0, code:0}; this._statusCfg = statCfg; + this._firstCall = true; this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); @@ -63,6 +68,8 @@ class Status extends Configurable { this._onKillOrgCb = null; this._onOrganismCb = null; this._onIpsCb = null; + this._status = null; + this._statusCfg = null; this.manager = null; this._oldValues = null; } @@ -111,21 +118,23 @@ class Status extends Configurable { if (stamp - this._stamp < this._statusCfg.period) {return} const status = this._status; const orgAmount = orgs.size || 1; + const fix = Status._toFixed; this.onBeforeStatus(ips, orgs); - status.ips = this._toFixed(ips, 2); - status.lps = this._toFixed(this._runLines / this._times, 0); + status.ips = fix(ips, 2); + status.lps = fix(this._runLines / this._times, 0); status.orgs = orgAmount; - status.energy = this._toFixed(this._curEnergy, 2); - status.iq = this._toFixed(this._energy * 100000, 3); - status.changes = this._toFixed(this._changes, 2); - status.fit = this._toFixed(this._fitness, 2); - status.age = this._toFixed(this._age / (this._ageCount || 1), 2); + status.energy = fix(this._curEnergy, 2); + status.iq = fix(this._energy * 100000, 3); + status.changes = fix(this._changes, 2); + status.fit = fix(this._fitness, 2); + status.age = fix(this._age / (this._ageCount || 1), 2); status.code = +(this._codeSize / orgAmount).toFixed(2); - this.onStatus(status, orgs.size); + !this._firstCall && this.onStatus(status, orgs.size); this.onAfterStatus(stamp); + this._firstCall = false; } _onOrganism(org, lines) { @@ -138,10 +147,6 @@ class Status extends Configurable { this._age += org.iterations; this._ageCount++; } - - _toFixed(val, fixed) { - return +val.toFixed(val < 10 && val > -10 ? fixed : 0); - } } module.exports = Status; \ No newline at end of file From d7e4344dad3f2e5f7bb2fcb6ac486df08a3c1162 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 15 Jan 2018 10:34:12 +0200 Subject: [PATCH 126/291] updated current version to 0.2.1.1 --- client/src/manager/Manager.js | 2 +- client/src/manager/plugins/status/charts/Charts.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 22af1e2..a8e84d1 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -52,7 +52,7 @@ class Manager extends Observer { * It may be used in a user console by the Operator of construct. Plugins * may add their methods to this map also. */ - this.api = {version: () => '0.2.0'}; + this.api = {version: () => '0.2.1.1'}; hasView && (this.api.visualize = this._visualize.bind(this)); /** diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index b8ec446..2265230 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -53,6 +53,7 @@ class Charts extends Status { //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); // TODO: this code should be moved to separate plugin + // TODO: add energy, orgs and code: e:xxx, o:xxx, c:xxx //const active = man.activeAround; //man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); From 4efefdf0c18dab724e4f52ac958825ba5498247c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 15 Jan 2018 11:58:43 +0200 Subject: [PATCH 127/291] added reset API method to man.api.charts namespace. so you may reset charts data any time from now, charts data will be collected if chart is not active changed version to 0.2.1 --- client/src/manager/Manager.js | 2 +- .../manager/plugins/status/charts/Chart.js | 29 ++++++++++++++----- .../manager/plugins/status/charts/Charts.js | 19 ++++++++++-- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index a8e84d1..c5c2ae8 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -52,7 +52,7 @@ class Manager extends Observer { * It may be used in a user console by the Operator of construct. Plugins * may add their methods to this map also. */ - this.api = {version: () => '0.2.1.1'}; + this.api = {version: () => '0.2.1'}; hasView && (this.api.visualize = this._visualize.bind(this)); /** diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index b7ad82b..bcdaef5 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -8,6 +8,7 @@ * @author flatline */ const GoogleCharts = require('google-charts').GoogleCharts; +const _get = require('lodash/get'); class Chart { constructor(title, cfg) { @@ -33,10 +34,10 @@ class Chart { * @return {Boolean} */ update(data) { - if (!this._ready || !this._cfg.active) {return false} + if (!this._ready) {return false} this._data.addRow(data); - this._chart.draw(this._data, this._options); + _get(this, '_cfg.active') && this._chart.draw(this._data, this._options); return true; } @@ -45,6 +46,12 @@ class Chart { set pos(p) {this._updatePos(p)} set active(a) {this._cfg.active !== a && this._updateActive(a)} + reset() { + if (!this._ready) {return false} + this._data = this._createDataTable(); + return true; + } + destroy() { this._cfg.active && this._chart.clearChart(); this._el.parentNode.removeChild(this._el); @@ -61,13 +68,10 @@ class Chart { el.style.opacity = this._cfg.transparent; this._updatePos(this._cfg.pos); document.body.appendChild(el); - - this._data = new google.visualization.DataTable(); - this._chart = new google.visualization.LineChart(el); this._ready = true; - this._data.addColumn('string', 'horizontal'); - this._data.addColumn('number', 'vertical'); + this._chart = new google.visualization.LineChart(el); + !this._data && (this._data = this._createDataTable()); } /** @@ -108,9 +112,18 @@ class Chart { } else { this._chart.clearChart(); this._el.parentNode.removeChild(this._el); - this._data = this._chart = this._el = null; + this._chart = this._el = null; } } + + _createDataTable() { + const data = new google.visualization.DataTable(); + + data.addColumn('string', 'horizontal'); + data.addColumn('number', 'vertical'); + + return data; + } } module.exports = Chart; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 2265230..7e2fb16 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -8,11 +8,14 @@ const Status = require('./../Status'); const Chart = require('./Chart'); const Config = require('./Config'); const _each = require('lodash/each'); +const _has = require('lodash/has'); +const _get = require('lodash/get'); const API = { transparent: ['_transparent', 'Sets transparent level' ], pos : ['_pos', 'Sets chart position' ], - active : ['_active', 'Activates/Deactivates chart'] + active : ['_active', 'Activates/Deactivates chart'], + reset : ['_reset', 'Resets chart data' ] }; class Charts extends Status { @@ -96,9 +99,19 @@ class Charts extends Status { */ _active(chart, a) {this._setProperty(chart, 'active', a)} + /** + * Resets chart data. It means, that chart will be refreshed with + * data started from this moment and further + * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @api + */ + _reset(chart) { + _get(this, `_charts.${chart}`, {}).reset && this._charts[chart].reset(); + } + _setProperty(chart, prop, val) { - this._charts[chart][prop] = val; - this.cfg.charts[chart][prop] = val; + this._charts[chart][prop] = val; + _has(this.cfg, `charts.${chart}.${prop}`) && (this.cfg.charts[chart][prop] = val); } } From 51cc8519bf476fa9d623128545625ab9c596ec46 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 15 Jan 2018 12:50:44 +0200 Subject: [PATCH 128/291] added man.api.reset() for resetting all charts added man.api.active(Boolean) for all charts --- .../src/manager/plugins/organisms/Config.js | 2 +- .../manager/plugins/status/charts/Charts.js | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 683cd8f..35d133c 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -134,7 +134,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 3000, + orgMaxOrgs: 1000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 7e2fb16..474ec26 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -92,21 +92,34 @@ class Charts extends Status { /** * Sets current chart position. Available positions: * top, down, left, right, topleft, downleft, topright, - * downright, full. + * downright, full. This method may be called with one + * Boolean parameter. In this case all charts will be activated + * or deactivated. * @param {String} chart Chart name, e.g: 'energy', or 'iq' - * @param {Boolean} a New active state + * @param {Boolean=} a New active state * @api */ - _active(chart, a) {this._setProperty(chart, 'active', a)} + _active(chart, a) { + if (typeof a === 'undefined') { + _each(this._charts, (c, k) => this._setProperty(k, 'active', chart)); + } else { + this._setProperty(chart, 'active', a); + } + } /** * Resets chart data. It means, that chart will be refreshed with - * data started from this moment and further + * data started from this moment and further. You may call this + * method without parameters to reset all charts. * @param {String} chart Chart name, e.g: 'energy', or 'iq' * @api */ _reset(chart) { - _get(this, `_charts.${chart}`, {}).reset && this._charts[chart].reset(); + if (typeof chart === 'undefined') { + _each(this._charts, c => {c.reset(); return true}); + } else { + _get(this, `_charts.${chart}`, {}).reset && this._charts[chart].reset(); + } } _setProperty(chart, prop, val) { From e2bdcaf7b364ebfee91580e2688b417c8581d9de Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 16 Jan 2018 23:23:21 +0200 Subject: [PATCH 129/291] refactored Organism class added new charts and fixed old added new global events updated Status plugin fixed an issue with grabbing energy between two organisms (cheat was found) fixed an issue of no mutations state of population if population reaches maximum code size change and delete mutations are available from now fixed an issue of reaching maximum size of code improved charts style (added more grid lines, removed extra margins) added 4x4 charts mode changed time format on charts add multi transparent mode changed logic of calculation of main parameters in Status plugin --- client/src/manager/ManagerSpec.js | 4 +- .../src/manager/plugins/organisms/Config.js | 22 +- .../src/manager/plugins/organisms/Mutator.js | 36 ++-- .../src/manager/plugins/organisms/Organism.js | 66 +++--- .../manager/plugins/organisms/Organisms.js | 30 ++- .../manager/plugins/organisms/dos/Organism.js | 2 +- .../plugins/organisms/dos/OrganismSpec.js | 2 +- .../plugins/organisms/dos/Organisms.js | 32 ++- .../plugins/organisms/garmin/Organism.js | 2 +- client/src/manager/plugins/status/Status.js | 200 ++++++++++++------ .../manager/plugins/status/charts/Chart.js | 58 +++-- .../manager/plugins/status/charts/Charts.js | 67 ++++-- .../manager/plugins/status/charts/Config.js | 29 ++- .../manager/plugins/status/console/Console.js | 24 +-- client/src/share/Events.js | 39 ++-- client/src/view/Canvas.js | 2 +- client/src/vm/VM.js | 10 +- 17 files changed, 414 insertions(+), 211 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 0d3a39b..f4e55ac 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -737,7 +737,7 @@ describe("client/src/manager/Manager", () => { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() - man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); + man1.on(EVENTS.KILL, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); man2.on(EVENTS.STEP_IN, () => stepInFlag = true); } else if (destroyFlag && stepInFlag && stepInBack) { @@ -812,7 +812,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 0 && org1 === null) { org1 = man1.organisms.first.val; org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() - man1.on(EVENTS.KILL_ORGANISM, () => destroyFlag = true); + man1.on(EVENTS.KILL, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); } else if (destroyFlag && stepInBack) { stepInBack = false; diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 35d133c..126bcf7 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -32,20 +32,20 @@ const Config = { * bigger then other, then it will be decreased to zero lines * of vm and organism will die. * Format: [ - * add - Probability of adding new line to the code * change - Probability of changing existing line of code * delete - Probability of deleting a line of code * small-change - Probability of "small change" - change part of one code line * clone - Probability for sharing of energy percent on clone - * copy - Probability of copying of code lines inside it's own code * period - Probability of period of organism mutations * amount - Probability of amount of mutations per period * probs - Probability of change one of probability coefficient in this array * clone-percent - Probability of change clone energy percent value * clone-period - Probability of change clone period value + * add - Probability of adding new line to the code + * copy - Probability of copying of code lines inside it's own code * ] */ - orgMutationProbs: [10,1,1,100,1,1,1,1,1,1,1], + orgMutationProbs: [1,1,100,1,1,1,1,1,1,10,1], /** * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) @@ -59,19 +59,19 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 200, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 100, + orgTournamentPeriod: 50, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 0, + orgRandomOrgPeriod: 200, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -92,7 +92,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 3000, + orgAlivePeriod: 30000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -134,7 +134,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 800, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -142,17 +142,17 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 80, + codeMaxSize: 50, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 300, + orgStartAmount: 800, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 50000, + orgStartEnergy: 100000, /** * {Number} Begin color of "empty" organism (organism without code). Color * should be set in HEX-RGB mode. Example: 0xRRGGBB diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 96b2773..a69b4e0 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -20,12 +20,9 @@ const MAX_VAR = Num.MAX_VAR; const MAX_BITS = Num.MAX_BITS; const BITS_PER_VAR = Num.BITS_PER_VAR; -class Mutator { - static _onAdd(org) { - org.vm.insertLine(); - org.changes += MAX_BITS; - } +const ADD_MUTAION_INDEX = 9; +class Mutator { static _onChange(org) { const vm = org.vm; vm.updateLine(Helper.rand(vm.size), Num.get()); @@ -65,10 +62,6 @@ class Mutator { org.changes++; } - static _onCopy(org) { - org.changes += (org.vm.copyLines() * MAX_BITS); - } - static _onPeriod(org) { org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod); org.changes++; @@ -94,24 +87,33 @@ class Mutator { org.changes++; } + static _onAdd(org) { + org.vm.insertLine(); + org.changes += MAX_BITS; + } + + static _onCopy(org) { + org.changes += (org.vm.copyLines() * MAX_BITS); + } + constructor(manager) { this._manager = manager; this._MUTATION_TYPES = [ - Mutator._onAdd, Mutator._onChange, Mutator._onDel, Mutator._onSmallChange, Mutator._onClone, - Mutator._onCopy, Mutator._onPeriod, Mutator._onAmount, Mutator._onProbs, Mutator._onCloneEnergyPercent, - Mutator._onClonePeriod + Mutator._onClonePeriod, + Mutator._onAdd, + Mutator._onCopy ]; manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); - manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); + manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); } destroy() { @@ -144,8 +146,12 @@ class Mutator { let type; for (let i = 0; i < mutations; i++) { - if (vm.size > maxSize) {mutations = i; break} - type = vm.size < 1 ? 0 : probIndex(org.mutationProbs); + // + // If we reach code size maximum, then only change and delete + // mutations may be applied to organism's code + // + type = vm.size < 1 ? ADD_MUTAION_INDEX : probIndex(org.mutationProbs); + if (vm.size >= maxSize && type >= ADD_MUTAION_INDEX) {mutations = i; break} mTypes[type](org); } this._manager.fire(EVENTS.MUTATIONS, org, mutations, clone); diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 4ff8537..9944653 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -5,12 +5,24 @@ * TODO: - * @author flatline */ -const Observer = require('./../../../../../common/src/Observer'); -const Helper = require('./../../../../../common/src/Helper'); -const OConfig = require('./../../../manager/plugins/organisms/Config'); -const EVENTS = require('./../../../share/Events').EVENTS; -const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; -const VM = require('./../../../vm/VM'); +const Observer = require('./../../../../../common/src/Observer'); +const Helper = require('./../../../../../common/src/Helper'); +const OConfig = require('./../../../manager/plugins/organisms/Config'); +const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; +const VM = require('./../../../vm/VM'); + +const GRAB_ENERGY = 0; +const DESTROY = 1; +const CLONE = 2; +const KILL_NO_ENERGY = 3; +const KILL_AGE = 4; +const ORG_EVENTS = { + GRAB_ENERGY, + DESTROY, + CLONE, + KILL_NO_ENERGY, + KILL_AGE +}; const IS_NUM = Helper.isNumeric; @@ -87,13 +99,8 @@ class Organism extends Observer { set clonePeriod(p) {this._clonePeriod = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set energy(e) { - this._energy = e; - } - set changes(c) { - this._changes = c; - this._updateColor(c); - } + set energy(e) {this._energy = e} + set changes(c) {this._updateColor(this._changes = c)} /** * Runs one code iteration (amount of lines set in Config.codeYieldPeriod) and returns @@ -107,8 +114,8 @@ class Organism extends Observer { if (this.alive) { this.vm.size === 0 && this._onCodeEnd(this, 0); - this._updateClone(); - this.alive && this._updateDestroy(); + this.alive && this._updateClone(); + this.alive && this._updateAge(); this.alive && this._updateEnergy(); } @@ -175,7 +182,7 @@ class Organism extends Observer { grabEnergy(amount) { if (!IS_NUM(amount)) {return true} const noEnergy = (this._energy -= amount) < 1; - this.fire(EVENTS.GRAB_ENERGY, amount + (noEnergy ? -this._energy : 0)); + this.fire(GRAB_ENERGY, amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); return !noEnergy; } @@ -185,7 +192,7 @@ class Organism extends Observer { } destroy() { - this.fire(EVENTS.DESTROY, this); + this.fire(DESTROY, this); this._alive = false; this._energy = 0; this._item = null; @@ -232,28 +239,37 @@ class Organism extends Observer { } /** - * Checks if organism need to be killed/destroyed, because of age or zero energy - * @return {Boolean} false means that organism was destroyed. + * Checks if organism need to be killed, because of age + * @return {Boolean} false means that organism was killed. */ - _updateDestroy() { + _updateAge() { const alivePeriod = OConfig.orgAlivePeriod; - const needDestroy = this._energy < 1 || this._iterations >= alivePeriod && alivePeriod > 0; + const needDestroy = this._iterations >= alivePeriod && alivePeriod > 0; - needDestroy && this.destroy(); + if (needDestroy) { + this.fire(KILL_AGE, this); + this.destroy(); + } return !needDestroy; } /** * This is how our system grabs an energy from organism every OConfig.orgEnergySpendPeriod - * period. + * period. If organism has zero energy, it will be killed also. * @return {Boolean} false means that organism was destroyed. */ _updateEnergy() { + if (this._energy < 1) { + this.fire(KILL_NO_ENERGY, this); + this.destroy(); + return true; + } if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} let grabSize = Math.round(this.vm.size / OConfig.orgGarbagePeriod); if (grabSize < 1) {grabSize = 1} + (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } @@ -263,9 +279,9 @@ class Organism extends Observer { */ _updateClone() { if (this._iterations % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0) {return true} - this.fire(EVENTS.CLONE, this); + this.fire(CLONE, this); return true; } } -module.exports = Organism; \ No newline at end of file +module.exports = {EVENTS: ORG_EVENTS, Organism}; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index db79455..3b6a5bb 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -12,6 +12,7 @@ const Config = require('./../../../../src/share/Config').Config; const OConfig = require('./Config'); const Console = require('./../../../../src/share/Console'); const EVENTS = require('./../../../../src/share/Events').EVENTS; +const ORG_EVENTS = require('./../../../../src/manager/plugins/organisms/Organism').EVENTS; //const Backup = require('./../backup/Backup'); const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); @@ -112,8 +113,10 @@ class Organisms extends Configurable { } addOrgHandlers(org) { - org.on(EVENTS.DESTROY, this._onKillOrg.bind(this)); - org.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); + org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); + org.on(ORG_EVENTS.CLONE, this._onCloneOrg.bind(this)); + org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); + org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); } reset() { @@ -256,7 +259,7 @@ class Organisms extends Configurable { this.organisms.del(org.item); this.world.setDot(org.x, org.y, 0); this.onAfterKillOrg(org); - this.parent.fire(EVENTS.KILL_ORGANISM, org); + this.parent.fire(EVENTS.KILL, org); //Console.info(org.id, ' die'); } @@ -264,6 +267,9 @@ class Organisms extends Configurable { this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); } + _onKillNoEnergyOrg(org) {this._parent.fire(EVENTS.KILL_NO_ENERGY, org)} + _onKillAgeOrg(org) {this._parent.fire(EVENTS.KILL_AGE, org)} + _updateCrossover(counter) { const orgAmount = this.organisms.size; if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} @@ -273,7 +279,10 @@ class Organisms extends Configurable { if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); - (orgAmount + 1) > OConfig.orgMaxOrgs && org1.destroy(); + if ((orgAmount + 1) > OConfig.orgMaxOrgs) { + this.parent.fire(EVENTS.KILL_OVERFLOW, org1); + org1.destroy(); + } return true; } @@ -287,7 +296,10 @@ class Organisms extends Configurable { if (org === newOrg) {return false} vm.generate(org.vm.size); - (orgAmount + 1) > OConfig.orgMaxOrgs && org.destroy(); + if ((orgAmount + 1) > OConfig.orgMaxOrgs) { + this.parent.fire(EVENTS.KILL_OVERFLOW, org); + org.destroy(); + } return true; } @@ -312,7 +324,13 @@ class Organisms extends Configurable { let org2 = this.randOrg(); if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} - this._tournament(org1, org2) === org2 ? org1.destroy() : org2.destroy(); + if (this._tournament(org1, org2) === org2) { + this.parent.fire(EVENTS.KILL_TOUR, org1); + org1.destroy(); + } else { + this.parent.fire(EVENTS.KILL_TOUR, org2); + org2.destroy(); + } return true; } diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 9215369..6dc5f7b 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -4,7 +4,7 @@ * TODO: - * @author flatline */ -const Organism = require('./../Organism'); +const Organism = require('./../Organism').Organism; const Operators = require('./Operators'); class OrganismDos extends Organism { diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index ad78b56..cad5269 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -2,7 +2,7 @@ // This spec covers two classes "Organism" and "OrganismDos" // describe("client/src/organism/OrganismDos", () => { - const eq = require('lodash/isEqual'); + const eq = require('lodash/isEqual'); const OrganismDos = require('./Organism'); const OConfig = require('./../../../../manager/plugins/organisms/Config'); const api = require('./../../../../share/Config').api; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 5bb9e74..3239a86 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -63,19 +63,23 @@ class Organisms extends BaseOrganisms { * @override */ onClone(org, child) { - const percent = org.cloneEnergyPercent; + const percent = org.cloneEnergyPercent; if (percent === 0.0) {return} - let energy = (((org.energy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() + const orgEnergy = org.energy; + const childEnergy = child.energy; + let energy = (((orgEnergy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() // // This is very special/rare case, when organisms cheating by creating // ancestors and put all energy into them at the same time resetting // their iterations property and make them immortal // - if (energy === org.energy) { + if (energy === orgEnergy) { energy--; } + orgEnergy <= energy && this.parent.fire(EVENTS.KILL_CLONE, org); org.grabEnergy(energy); - child.grabEnergy(child.energy - energy); + childEnergy <= (childEnergy - energy) && this.parent.fire(EVENTS.KILL_CLONE, child); + child.grabEnergy(childEnergy - energy); } addOrgHandlers(org) { @@ -145,10 +149,19 @@ class Organisms extends BaseOrganisms { const posId = Helper.posId(x, y); if (typeof(positions[posId]) === 'undefined') { - eat < 0 ? this.world.setDot(x, y, -eat) : (ret.ret = this.world.grabDot(x, y, eat)); + if (eat < 0) { + this.parent.fire(EVENTS.EAT_ENERGY, eat); + this.world.setDot(x, y, -eat); + } else { + ret.ret = this.world.grabDot(x, y, eat); + this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); + } } else { - ret.ret = eat < 0 ? 0 : (eat > positions[posId].energy ? positions[posId].energy : eat); - positions[posId].grabEnergy(eat); + const victimOrg = positions[posId]; + ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); + this.parent.fire(EVENTS.EAT_ORG, ret.ret, victimOrg); + victimOrg.energy <= eat && this.parent.fire(EVENTS.KILL_EAT, victimOrg); + victimOrg.grabEnergy(ret.ret); } } @@ -178,6 +191,7 @@ class Organisms extends BaseOrganisms { org.x = x2; org.y = y2; man.fire(EVENTS.STEP_OUT, x2, y2, dir, org); + man.fire(EVENTS.KILL_STEP_OUT, org); org.x = x1; org.y = y1; org.destroy(); @@ -219,7 +233,9 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - org.grabEnergy((((org.energy * OConfig.orgStepEnergySpendPercent) + 0.5) << 1) >>> 1); + const energy = (((org.energy * OConfig.orgStepEnergySpendPercent) + 0.5) << 1) >>> 1; + (org.energy <= energy) && this.parent.fire(EVENTS.KILL_STEP_IN, org); + org.grabEnergy(energy); } } diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index c0a0dd8..b422dc8 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -4,7 +4,7 @@ * TODO: - * @author flatline */ -const Organism = require('./../Organism'); +const Organism = require('./../Organism').Organism; const Operators = require('./Operators'); const Config = require('./../../../../share/Config').Config; const EVENTS = require('./../../../../share/Events').EVENTS; diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 6f99cbf..ebed8ef 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -1,6 +1,6 @@ /** * Base class for plugin which collects real time data about system like: - * population energy, changes, organisms iq etc and provide this data to + * population energy, changes, organisms ips etc and provide this data to * other visualization classes (e.g. Charts). Output data is an object of * described below format: * @@ -10,13 +10,13 @@ * per one second * org: Average amount of organisms at the moment of logging * nrg: Amount of energy of average organism - * iq : Energy picking speed per status period * che: Changes amount of average organism * fit: Fitness of average organism * cod: Code size of average organism * * @author flatline */ +const _fill = require('lodash/fill'); const EVENTS = require('./../../../share/Events').EVENTS; const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; @@ -37,47 +37,94 @@ class Status extends Configurable { constructor(manager, statCfg, apiCfg = {}) { super(manager, {Config, cfg: statCfg}, apiCfg); - this.manager = manager; - this._stamp = 0; - this._curEnergy = 0; - this._energy = 0; - this._fitness = 0; - this._changes = 0; - this._codeSize = 0; - this._runLines = 1; - this._age = 0; - this._ageCount = 0; - this._times = 0; - this._oldValues = [0, 0, 0]; - this._status = {ips:0, lps:0, orgs:0, energy:0, iq:0, changes:0, fit:0, age:0, code:0}; - this._statusCfg = statCfg; - this._firstCall = true; - this._onIpsCb = this._onIps.bind(this); - this._onOrganismCb = this._onOrganism.bind(this); - this._onKillOrgCb = this._onKillOrg.bind(this); - - manager.on(EVENTS.IPS, this._onIpsCb); - manager.on(EVENTS.ORGANISM, this._onOrganismCb); - manager.on(EVENTS.KILL_ORGANISM, this._onKillOrgCb); + this.manager = manager; + this._status = { + ips :0, lps :0, orgs :0, energy :0, paenergy:0, penergy:0, changes:0, fit :0, age :0, code:0, + kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killtour:0, killclone:0 + }; + this._stamp = 0; + this._energy = 0; + this._eatAll = 0; + this._eatEnergy = 0; + this._fitness = 0; + this._changes = 0; + this._codeSize = 0; + this._runLines = 1; + this._age = 0; + this._ageCount = 0; + this._times = 0; + this._kill = new Array(9); + this._statusCfg = statCfg; + this._firstCall = true; + + this._onIpsCb = this._onIps.bind(this); + this._onOrganismCb = this._onOrganism.bind(this); + this._onEatEnergyCb = this._onEatEnergy.bind(this); + this._onEatOrgCb = this._onEatOrg.bind(this); + this._onKillOrgCb = this._onKillOrg.bind(this); + this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); + this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 2); + this._onKillEatCb = this._onKillHandlerOrg.bind(this, 3); + this._onKillOverCb = this._onKillHandlerOrg.bind(this, 4); + this._onKillOutCb = this._onKillHandlerOrg.bind(this, 5); + this._onKillInCb = this._onKillHandlerOrg.bind(this, 6); + this._onKillTourCb = this._onKillHandlerOrg.bind(this, 7); + this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); + + manager.on(EVENTS.IPS, this._onIpsCb); + manager.on(EVENTS.ORGANISM, this._onOrganismCb); + manager.on(EVENTS.EAT_ORG, this._onEatOrgCb); + manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + manager.on(EVENTS.KILL, this._onKillOrgCb); + manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); + manager.on(EVENTS.KILL_AGE, this._onKillAgeCb); + manager.on(EVENTS.KILL_EAT, this._onKillEatCb); + manager.on(EVENTS.KILL_OVERFLOW, this._onKillOverCb); + manager.on(EVENTS.KILL_STEP_OUT, this._onKillOutCb); + manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); + manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); + manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); + + _fill(this._kill, 0); } destroy() { - this.manager.off(EVENTS.KILL_ORGANISM, this._onKillOrgCb); - this.manager.off(EVENTS.ORGANISM, this._onOrganismCb); - this.manager.off(EVENTS.IPS, this._onIpsCb); - this._onKillOrgCb = null; - this._onOrganismCb = null; - this._onIpsCb = null; - this._status = null; - this._statusCfg = null; - this.manager = null; - this._oldValues = null; + const man = this.manager; + + man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); + man.off(EVENTS.KILL_TOUR, this._onKillTourCb); + man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); + man.off(EVENTS.KILL_STEP_OUT, this._onKillOutCb); + man.off(EVENTS.KILL_OVERFLOW, this._onKillOverCb); + man.off(EVENTS.KILL_EAT, this._onKillEatCb); + man.off(EVENTS.KILL_AGE, this._onKillAgeCb); + man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); + man.off(EVENTS.KILL, this._onKillOrgCb); + man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + man.off(EVENTS.EAT_ORG, this._onEatOrgCb); + man.off(EVENTS.ORGANISM, this._onOrganismCb); + man.off(EVENTS.IPS, this._onIpsCb); + + this._onKillOrgCb = null; + this._onOrganismCb = null; + this._onEatOrgCb = null; + this._onEatEnergyCb = null; + this._onKillCloneCb = null; + this._onKillTourCb = null; + this._onKillInCb = null; + this._onKillOutCb = null; + this._onKillOverCb = null; + this._onKillEatCb = null; + this._onKillAgeCb = null; + this._onKillEnergyCb = null; + this._onIpsCb = null; + this._status = null; + this._statusCfg = null; + this.manager = null; } onBeforeStatus(ips, orgs) { - const olds = this._oldValues; const size = orgs.size || 1; - const lines = this._runLines || 1; let energy = 0; let fitness = 0; let changes = 0; @@ -86,29 +133,28 @@ class Status extends Configurable { let org; while(item && (org = item.val)) { - energy += org.energy; - changes += org.changes; - fitness += org.fitness(); - codeSize += org.vm.size; - item = item.next; + energy += org.energy; + changes += org.changes; + fitness += org.fitness(); + codeSize += org.vm.size; + item = item.next; } - energy /= size; - fitness /= size; - this._curEnergy = energy; - this._energy = (energy - olds[0]) / lines; - this._changes = (changes - olds[1]) / size; - this._fitness = (fitness - olds[2]) / lines; - this._codeSize = codeSize; - this._oldValues = [energy, changes, fitness]; + this._energy = energy / size; + this._changes = changes / size; + this._fitness = fitness / size; + this._codeSize = codeSize; } onAfterStatus(stamp) { - this._times = 0; - this._runLines = 0; - this._age = 0; - this._ageCount = 0; - this._stamp = stamp; + this._times = 0; + this._runLines = 0; + this._age = 0; + this._ageCount = 0; + this._eatEnergy = 0; + this._eatAll = 0; + this._stamp = stamp; + _fill(this._kill, 0); } _onIps(ips, orgs) { @@ -122,15 +168,25 @@ class Status extends Configurable { this.onBeforeStatus(ips, orgs); - status.ips = fix(ips, 2); - status.lps = fix(this._runLines / this._times, 0); - status.orgs = orgAmount; - status.energy = fix(this._curEnergy, 2); - status.iq = fix(this._energy * 100000, 3); - status.changes = fix(this._changes, 2); - status.fit = fix(this._fitness, 2); - status.age = fix(this._age / (this._ageCount || 1), 2); - status.code = +(this._codeSize / orgAmount).toFixed(2); + status.ips = fix(ips, 2); + status.lps = fix(this._runLines / this._times, 0); + status.orgs = orgAmount; + status.energy = fix(this._energy, 2); + status.paenergy = fix(this._eatAll / orgAmount, 2); + status.penergy = fix(this._eatEnergy / orgAmount, 2); + status.changes = fix(this._changes, 2); + status.fit = fix(this._fitness / 10000000, 2); + status.age = fix(this._age / (this._ageCount || 1), 2); + status.code = +(this._codeSize / orgAmount).toFixed(2); + status.kill = fix(this._kill[0], 2); + status.killenergy = fix(this._kill[1], 2); + status.killage = fix(this._kill[2], 2); + status.killeat = fix(this._kill[3], 2); + status.killover = fix(this._kill[4], 2); + status.killout = fix(this._kill[5], 2); + status.killin = fix(this._kill[6], 2); + status.killtour = fix(this._kill[7], 2); + status.killclone = fix(this._kill[8], 2); !this._firstCall && this.onStatus(status, orgs.size); this.onAfterStatus(stamp); @@ -142,11 +198,29 @@ class Status extends Configurable { this._runLines += lines; } + /** + * Calculates eat energy excluding eating other organisms + * @param {Number} eat Amount of eat energy + */ + _onEatEnergy(eat) { + this._eatEnergy += eat; + this._eatAll += eat; + } + + _onEatOrg(eat) { + this._eatAll += eat; + } + _onKillOrg(org) { if (!this._statusCfg.active) {return} this._age += org.iterations; + this._kill[0]++; this._ageCount++; } + + _onKillHandlerOrg(index) { + this._kill[index]++; + } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index bcdaef5..399e9c1 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -14,10 +14,10 @@ class Chart { constructor(title, cfg) { this._options = { title : title, - hAxis : {textStyle: {fontSize: 12}}, - vAxis : {textStyle: {fontSize: 12}}, + hAxis : {textStyle: {fontSize: 10}}, + vAxis : {textStyle: {fontSize: 10}, gridlines: {count: 10}}, legend : 'none', - chartArea: {left: 100, top: 50, bottom: 60, width: '100%', height: '100%'}, + chartArea: {left: 80, top: 30, bottom: 50, width: '100%', height: '100%'}, }; this._data = null; this._chart = null; @@ -42,7 +42,7 @@ class Chart { return true; } - set transparent(t) {this._el.style.opacity = t} + set transparent(t) {this._el && (this._el.style.opacity = t)} set pos(p) {this._updatePos(p)} set active(a) {this._cfg.active !== a && this._updateActive(a)} @@ -83,15 +83,47 @@ class Chart { */ _getSize(pos) { return { - top : ['100%', '50%', '0', '0' ], - down : ['100%', '50%', '0', '50%'], - left : ['50%', '100%', '0', '0' ], - right : ['50%', '100%', '50%', '0' ], - topleft : ['50%', '50%', '0', '0' ], - downleft : ['50%', '50%', '0', '50%'], - topright : ['50%', '50%', '50%', '0' ], - downright: ['50%', '50%', '50%', '50%'], - full : ['100%', '100%', '0', '0' ] + full : ['100%', '100%', '0', '0' ], + + top : ['100%', '50%', '0', '0' ], + down : ['100%', '50%', '0', '50%' ], + left : ['50%', '100%', '0', '0' ], + right : ['50%', '100%', '50%', '0' ], + + topleft : ['50%', '50%', '0', '0' ], + downleft : ['50%', '50%', '0', '50%' ], + topright : ['50%', '50%', '50%', '0' ], + downright: ['50%', '50%', '50%', '50%' ], + + '0-0|9' : ['33.3%', '33.3%', '0', '0' ], + '1-0|9' : ['33.3%', '33.3%', '33.3%', '0' ], + '2-0|9' : ['33.3%', '33.3%', '66.6%', '0' ], + '0-1|9' : ['33.3%', '33.3%', '0', '33.3%'], + '1-1|9' : ['33.3%', '33.3%', '33.3%', '33.3%'], + '2-1|9' : ['33.3%', '33.3%', '66.6%', '33.3%'], + '0-2|9' : ['33.3%', '33.3%', '0', '66.6%'], + '1-2|9' : ['33.3%', '33.3%', '33.3%', '66.6%'], + '2-2|9' : ['33.3%', '33.3%', '66.6%', '66.6%'], + + '0-0|16' : ['25%', '25%', '0', '0' ], + '1-0|16' : ['25%', '25%', '25%', '0' ], + '2-0|16' : ['25%', '25%', '50%', '0' ], + '3-0|16' : ['25%', '25%', '75%', '0' ], + + '0-1|16' : ['25%', '25%', '0', '25%' ], + '1-1|16' : ['25%', '25%', '25%', '25%' ], + '2-1|16' : ['25%', '25%', '50%', '25%' ], + '3-1|16' : ['25%', '25%', '75%', '25%' ], + + '0-2|16' : ['25%', '25%', '0', '50%' ], + '1-2|16' : ['25%', '25%', '25%', '50%' ], + '2-2|16' : ['25%', '25%', '50%', '50%' ], + '3-2|16' : ['25%', '25%', '75%', '50%' ], + + '0-3|16' : ['25%', '25%', '0', '75%' ], + '1-3|16' : ['25%', '25%', '25%', '75%' ], + '2-3|16' : ['25%', '25%', '50%', '75%' ], + '3-3|16' : ['25%', '25%', '75%', '75%' ] }[pos]; } diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 474ec26..eca58bb 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -21,18 +21,29 @@ const API = { class Charts extends Status { constructor(manager) { super(manager, Config, API); + const periodSec = Config.period / 1000; this._data = new Array(2); this._charts = { - ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), - lps : new Chart('LPS - Lines Per Second', Config.charts.lps), - orgs : new Chart('Amount of organisms', Config.charts.orgs), - energy : new Chart('Average organism energy', Config.charts.energy), - iq : new Chart('Average organism IQ (Energy pick speed)', Config.charts.iq), - changes: new Chart('Average organism changes (Mutations)', Config.charts.changes), - fit : new Chart('Average organism Fitness', Config.charts.fit), - age : new Chart('Average organism Age', Config.charts.age), - code : new Chart('Average organism code size', Config.charts.code) + ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), + lps : new Chart('LPS - Lines Per Second', Config.charts.lps), + orgs : new Chart('Amount of organisms', Config.charts.orgs), + energy : new Chart('Average organism energy', Config.charts.energy), + paenergy : new Chart('Average organism\'s picked energy (all)', Config.charts.paenergy), + penergy : new Chart('Average organism\'s picked energy (energy only)', Config.charts.penergy), + changes : new Chart('Average organism\'s changes (Mutations)', Config.charts.changes), + fit : new Chart('Average organism\'s Fitness', Config.charts.fit), + age : new Chart('Average organism\'s Age', Config.charts.age), + code : new Chart('Average organism\'s code size', Config.charts.code), + kill : new Chart(`Amount of killed organisms per ${periodSec} sec (all)`, Config.charts.kill), + killenergy: new Chart(`Amount of killed organisms with 0 energy per ${periodSec} sec`, Config.charts.killenergy), + killage : new Chart(`Amount of killed organisms with max age per ${periodSec} sec`, Config.charts.killage), + killeat : new Chart(`Amount of killed organisms eat by other per ${periodSec} sec`, Config.charts.killeat), + killover : new Chart(`Amount of organisms killed after overflow per ${periodSec} sec`, Config.charts.killover), + killout : new Chart(`Amount of organisms killed after step out per ${periodSec} sec`, Config.charts.killout), + killin : new Chart(`Amount of organisms killed after step in per ${periodSec} sec`, Config.charts.killin), + killtour : new Chart(`Amount of organisms killed in tournament per ${periodSec} sec`, Config.charts.killtour), + killclone : new Chart(`Amount of organisms killed during clone per ${periodSec} sec`, Config.charts.killclone) }; } @@ -51,10 +62,7 @@ class Charts extends Status { * @override */ onStatus(status, orgs) { - const stamp = Date.now(); - const time = new Date(stamp); - - //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${paenergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); // TODO: this code should be moved to separate plugin // TODO: add energy, orgs and code: e:xxx, o:xxx, c:xxx //const active = man.activeAround; @@ -63,7 +71,7 @@ class Charts extends Status { const data = this._data; const charts = this._charts; - data[0] = `${time.getHours()}:${time.getMinutes()}`; + data[0] = this._to12h(new Date); _each(charts, (chart, key) => { data[1] = status[key]; @@ -71,19 +79,36 @@ class Charts extends Status { }); } + _to12h(time) { + let hours = time.getHours(); + let minutes = time.getMinutes(); + + hours = hours % 12; + hours = hours ? hours : 12; + + return hours + ':' + minutes; + } + /** - * Sets current chart transparent coefficient - * @param {String} chart Chart name, e.g: 'energy', or 'iq' - * @param {Number} t Value between 0...1 + * Sets specified chart transparent coefficient. May be called + * with one Number parameter to set it for all charts. + * @param {String|Number} chart Chart name, e.g: 'energy', or 'ips' or opacity value + * @param {Number=} t Value between 0...1 or undefined * @api */ - _transparent(chart, t) {this._setProperty(chart, 'transparent', t)} + _transparent(chart, t) { + if (typeof t === 'undefined') { + _each(this._charts, (c, k) => this._setProperty(k, 'transparent', chart)); + } else { + this._setProperty(chart, 'transparent', t); + } + } /** * Sets current chart position. Available positions: * top, down, left, right, topleft, downleft, topright, * downright, full. - * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {String} chart Chart name, e.g: 'energy', or 'ips' * @param {String} p new position * @api */ @@ -95,7 +120,7 @@ class Charts extends Status { * downright, full. This method may be called with one * Boolean parameter. In this case all charts will be activated * or deactivated. - * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {String|Boolean} chart Chart name, e.g: 'energy', or 'ips' * @param {Boolean=} a New active state * @api */ @@ -111,7 +136,7 @@ class Charts extends Status { * Resets chart data. It means, that chart will be refreshed with * data started from this moment and further. You may call this * method without parameters to reset all charts. - * @param {String} chart Chart name, e.g: 'energy', or 'iq' + * @param {String=} chart Chart name, e.g: 'energy', or 'ips' * @api */ _reset(chart) { diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 07721d1..1b5884c 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -16,16 +16,25 @@ const Config = { * {Object} Available chart types */ charts: { - ips : {pos: 'topleft', active: false, transparent: 0.6}, - lps : {pos: 'downleft', active: false, transparent: 0.6}, - orgs : {pos: 'topright', active: false, transparent: 0.6}, - energy : {pos: 'downright', active: true, transparent: 0.6}, - iq : {pos: 'topleft', active: true, transparent: 0.6}, - changes: {pos: 'downleft', active: false, transparent: 0.6}, - fit : {pos: 'topright', active: true, transparent: 0.6}, - age : {pos: 'downright', active: false, transparent: 0.6}, - code : {pos: 'downleft', active: true, transparent: 0.6} - + ips : {pos: 'topleft', active: false, transparent: 0.6}, + lps : {pos: 'downleft', active: false, transparent: 0.6}, + killout : {pos: 'topright', active: false, transparent: 0.6}, + orgs : {pos: '0-0|16', active: true, transparent: 0.6}, + energy : {pos: '0-1|16', active: true, transparent: 0.6}, + paenergy : {pos: '0-2|16', active: true, transparent: 0.6}, + penergy : {pos: '0-3|16', active: true, transparent: 0.6}, + fit : {pos: '1-0|16', active: true, transparent: 0.6}, + age : {pos: '1-1|16', active: true, transparent: 0.6}, + code : {pos: '1-2|16', active: true, transparent: 0.6}, + kill : {pos: '1-3|16', active: true, transparent: 0.6}, + killenergy: {pos: '2-0|16', active: true, transparent: 0.6}, + killage : {pos: '2-1|16', active: true, transparent: 0.6}, + killeat : {pos: '2-2|16', active: true, transparent: 0.6}, + killover : {pos: '2-3|16', active: true, transparent: 0.6}, + changes : {pos: '3-0|16', active: true, transparent: 0.6}, + killin : {pos: '3-1|16', active: true, transparent: 0.6}, + killtour : {pos: '3-2|16', active: true, transparent: 0.6}, + killclone : {pos: '3-3|16', active: true, transparent: 0.6} } }; diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 4163e38..0dd0c3d 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -1,7 +1,7 @@ /** * This plugin is a primitive version of real time charts. It shows * different parameters of the jevo.js system, like average energy, - * iq (energy picking speed), average code size and so on. Here + * ips (Iterations Per Second), average code size and so on. Here * labels explanation: * * ips: Iterations Per Second - amount of all organisms full @@ -10,7 +10,6 @@ * per one second * org: Average amount of organisms at the moment of logging * nrg: Amount of energy of average organism - * iq : Energy picking speed per StatusConfig.period seconds * che: Changes amount of average organism * fit: Fitness of average organism * cod: Code size of average organism @@ -47,18 +46,19 @@ class Console extends Status { const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; const conns = `con:${con === ' ' ? 'no ' : con}`; - const sips = format(status.ips, 'ips', 10); - const slps = format(status.lps, 'lps', 14); - const sorgs = format(orgs, 'org', 10); - const senergy = format(status.energy, 'nrg', 14); - const siq = format(status.iq, 'iq', 14); - const schanges = format(status.changes, 'che', 12); - const sfit = format(status.fit, 'fit', 13); - const sage = format(status.age, 'age', 11); - const scode = format(status.code, 'cod', 12); + const sips = format(status.ips, 'ips', 10); + const slps = format(status.lps, 'lps', 14); + const sorgs = format(orgs, 'org', 10); + const senergy = format(status.energy, 'nrg', 14); + const spaenergy = format(status.paenergy, 'anrg', 15); + const spenergy = format(status.penergy, 'pnrg', 15); + const schanges = format(status.changes, 'che', 12); + const sfit = format(status.fit, 'fit', 13); + const sage = format(status.age, 'age', 11); + const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${senergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spaenergy}${spenergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/share/Events.js b/client/src/share/Events.js index c84e074..2181437 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -4,6 +4,7 @@ * * @author flatline * TODO: find unused and remove. But after main code is done. + * TODO: describe all events */ const EVENTS = { ITERATION : 0, @@ -13,20 +14,30 @@ const EVENTS = { ORGANISM : 4, GRAB_ENERGY : 5, UPDATE_ENERGY : 6, - KILL_ORGANISM : 7, - MUTATIONS : 8, - CLONE : 9, - EAT : 10, - STEP : 11, - STEP_OUT : 12, - STEP_IN : 13, - BORN_ORGANISM : 14, - GET_ENERGY : 15, - DESTROY : 16, - RUN : 17, - STOP : 18, - RESET_CODE : 19, - CHECK_AT : 20 + KILL : 7, // general kill event + KILL_NO_ENERGY : 8, // killed if zero energy + KILL_AGE : 9, // killed if max age reached + KILL_EAT : 10, // killed, because other organism has eat this one + KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 12, // killed, because organism step outside the world + KILL_STEP_IN : 13, // killed, because of panishment for step in from near client + KILL_TOUR : 14, // killed in tournament + KILL_CLONE : 15, // killed, because of lack of energy after clone + MUTATIONS : 16, + CLONE : 17, + EAT : 18, + EAT_ORG : 19, + EAT_ENERGY : 20, + STEP : 21, + STEP_OUT : 22, + STEP_IN : 23, + BORN_ORGANISM : 24, + GET_ENERGY : 25, + DESTROY : 26, + RUN : 27, + STOP : 28, + RESET_CODE : 29, + CHECK_AT : 30 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index dad3606..2ec647c 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -126,7 +126,7 @@ class Canvas { _initPanZoomLib() { this._canvasEl.style.imageRendering = 'pixelated'; this._panZoom = Panzoom(this._canvasEl, { - zoomSpeed : 0.1, + zoomSpeed : 0.05, smoothScroll: false }); this._panZoom.zoomAbs(0, 0, 1.0); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index cbe90ea..69482af 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -168,12 +168,8 @@ class VM extends Observer { let end1 = rand(len1); let adds; - if (start > end) { - [start, end] = [end, start] - } - if (start1 > end1) { - [start1, end1] = [end1, start1] - } + if (start > end) {[start, end] = [end, start]} + if (start1 > end1) {[start1, end1] = [end1, start1]} adds = end1 - start1 - end + start; if (this._code.length + adds >= OConfig.codeMaxSize) { @@ -206,7 +202,7 @@ class VM extends Observer { // // Organism size should be less them codeMaxSize // - if (code.length + end - start >= OConfig.codeMaxSize) {return 0} + if (codeLen + end - start >= OConfig.codeMaxSize) {return 0} // // We may insert copied piece before "start" (0) or after "end" (1) // From c261f1e06d2f00a2a39b1e5ae8e28560a0fd6270 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 16 Jan 2018 23:29:46 +0200 Subject: [PATCH 130/291] added amount of killed organisms to the Console plugin --- client/src/manager/plugins/status/console/Console.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 0dd0c3d..c884ca0 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -52,13 +52,14 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 14); const spaenergy = format(status.paenergy, 'anrg', 15); const spenergy = format(status.penergy, 'pnrg', 15); + const skill = format(status.kill, 'kil', 14); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); const sage = format(status.age, 'age', 11); const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spaenergy}${spenergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spaenergy}${spenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } From e16451d7b888965831638fa6ce2dd91824b1e883 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 00:38:12 +0200 Subject: [PATCH 131/291] fixed an issue of overlapping of energy and energy put by organism added startEnergy to organisms --- .../src/manager/plugins/organisms/Organism.js | 6 ++ .../plugins/organisms/dos/Organisms.js | 7 +- client/src/manager/plugins/status/Status.js | 66 +++++++++---------- .../manager/plugins/status/charts/Charts.js | 6 +- .../manager/plugins/status/charts/Config.js | 4 +- .../manager/plugins/status/console/Console.js | 4 +- 6 files changed, 47 insertions(+), 46 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 9944653..587e9ec 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -88,6 +88,7 @@ class Organism extends Observer { get cloneEnergyPercent() {return this._cloneEnergyPercent} get clonePeriod() {return this._clonePeriod} get energy() {return this._energy} + get startEnergy() {return this._startEnergy} get color() {return this._color} get mem() {return this._mem} get posId() {return Helper.posId(this._x, this._y)} @@ -138,6 +139,7 @@ class Organism extends Observer { fnId : this._fnId, vm : this.vm.serialize(), energy : this._energy, + startEnergy : this._startEnergy, color : this._color, mutationProbs : this._mutationProbs, cloneMutationPercent: this._cloneMutationPercent, @@ -169,6 +171,7 @@ class Organism extends Observer { this._fnId = json.fnId; this.vm.unserialize(json.vm); this._energy = json.energy; + this._startEnergy = json.startEnergy; this._color = json.color; this._mutationProbs = json.mutationProbs; this._cloneMutationPercent = json.cloneMutationPercent; @@ -195,6 +198,7 @@ class Organism extends Observer { this.fire(DESTROY, this); this._alive = false; this._energy = 0; + this._startEnergy = 0; this._item = null; this._mem = null; this._mutationProbs = null; @@ -209,6 +213,7 @@ class Organism extends Observer { _create() { this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls); this._energy = OConfig.orgStartEnergy; + this._startEnergy = OConfig.orgStartEnergy; this._color = OConfig.orgStartColor; this._mutationProbs = OConfig.orgMutationProbs.slice(); this._cloneMutationPercent = OConfig.orgCloneMutationPercent; @@ -222,6 +227,7 @@ class Organism extends Observer { _clone(parent) { this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls, parent.vm); this._energy = parent.energy; + this._startEnergy = parent.energy; this._color = parent.color; this._mutationProbs = parent.mutationProbs.slice(); this._cloneMutationPercent = parent.cloneMutationPercent; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 3239a86..6046b38 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -150,8 +150,10 @@ class Organisms extends BaseOrganisms { const posId = Helper.posId(x, y); if (typeof(positions[posId]) === 'undefined') { if (eat < 0) { - this.parent.fire(EVENTS.EAT_ENERGY, eat); - this.world.setDot(x, y, -eat); + if (this.world.isFree(x, y)) { + this.parent.fire(EVENTS.EAT_ENERGY, eat); + this.world.setDot(x, y, -eat); + } } else { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); @@ -159,7 +161,6 @@ class Organisms extends BaseOrganisms { } else { const victimOrg = positions[posId]; ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); - this.parent.fire(EVENTS.EAT_ORG, ret.ret, victimOrg); victimOrg.energy <= eat && this.parent.fire(EVENTS.KILL_EAT, victimOrg); victimOrg.grabEnergy(ret.ret); } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index ebed8ef..4f0fca1 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -39,12 +39,12 @@ class Status extends Configurable { this.manager = manager; this._status = { - ips :0, lps :0, orgs :0, energy :0, paenergy:0, penergy:0, changes:0, fit :0, age :0, code:0, + ips :0, lps :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age :0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killtour:0, killclone:0 }; this._stamp = 0; this._energy = 0; - this._eatAll = 0; + this._pickEnergy = 0; this._eatEnergy = 0; this._fitness = 0; this._changes = 0; @@ -60,7 +60,6 @@ class Status extends Configurable { this._onIpsCb = this._onIps.bind(this); this._onOrganismCb = this._onOrganism.bind(this); this._onEatEnergyCb = this._onEatEnergy.bind(this); - this._onEatOrgCb = this._onEatOrg.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 2); @@ -73,7 +72,6 @@ class Status extends Configurable { manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.ORGANISM, this._onOrganismCb); - manager.on(EVENTS.EAT_ORG, this._onEatOrgCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); @@ -101,13 +99,11 @@ class Status extends Configurable { man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); - man.off(EVENTS.EAT_ORG, this._onEatOrgCb); man.off(EVENTS.ORGANISM, this._onOrganismCb); man.off(EVENTS.IPS, this._onIpsCb); this._onKillOrgCb = null; this._onOrganismCb = null; - this._onEatOrgCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; this._onKillTourCb = null; @@ -124,36 +120,39 @@ class Status extends Configurable { } onBeforeStatus(ips, orgs) { - const size = orgs.size || 1; - let energy = 0; - let fitness = 0; - let changes = 0; - let codeSize = 0; - let item = orgs.first; + const size = orgs.size || 1; + let energy = 0; + let startEnergy = 0; + let fitness = 0; + let changes = 0; + let codeSize = 0; + let item = orgs.first; let org; while(item && (org = item.val)) { - energy += org.energy; - changes += org.changes; - fitness += org.fitness(); - codeSize += org.vm.size; - item = item.next; + energy += org.energy; + startEnergy += org.startEnergy; + changes += org.changes; + fitness += org.fitness(); + codeSize += org.vm.size; + item = item.next; } - this._energy = energy / size; - this._changes = changes / size; - this._fitness = fitness / size; - this._codeSize = codeSize; + this._pickEnergy = (energy - startEnergy) / size; + this._energy = energy / size; + this._changes = changes / size; + this._fitness = fitness / size; + this._codeSize = codeSize; } onAfterStatus(stamp) { - this._times = 0; - this._runLines = 0; - this._age = 0; - this._ageCount = 0; - this._eatEnergy = 0; - this._eatAll = 0; - this._stamp = stamp; + this._times = 0; + this._runLines = 0; + this._age = 0; + this._ageCount = 0; + this._eatEnergy = 0; + this._pickEnergy = 0; + this._stamp = stamp; _fill(this._kill, 0); } @@ -172,8 +171,8 @@ class Status extends Configurable { status.lps = fix(this._runLines / this._times, 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); - status.paenergy = fix(this._eatAll / orgAmount, 2); - status.penergy = fix(this._eatEnergy / orgAmount, 2); + status.penergy = fix(this._pickEnergy, 2); + status.eenergy = fix(this._eatEnergy / orgAmount, 2); status.changes = fix(this._changes, 2); status.fit = fix(this._fitness / 10000000, 2); status.age = fix(this._age / (this._ageCount || 1), 2); @@ -199,16 +198,11 @@ class Status extends Configurable { } /** - * Calculates eat energy excluding eating other organisms + * Calculates eat energy, excluding eating other organisms * @param {Number} eat Amount of eat energy */ _onEatEnergy(eat) { this._eatEnergy += eat; - this._eatAll += eat; - } - - _onEatOrg(eat) { - this._eatAll += eat; } _onKillOrg(org) { diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index eca58bb..f02891b 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -29,8 +29,8 @@ class Charts extends Status { lps : new Chart('LPS - Lines Per Second', Config.charts.lps), orgs : new Chart('Amount of organisms', Config.charts.orgs), energy : new Chart('Average organism energy', Config.charts.energy), - paenergy : new Chart('Average organism\'s picked energy (all)', Config.charts.paenergy), - penergy : new Chart('Average organism\'s picked energy (energy only)', Config.charts.penergy), + penergy : new Chart('Average organism\'s picked energy (all)', Config.charts.penergy), + eenergy : new Chart('Average organism\'s picked energy (energy only)', Config.charts.eenergy), changes : new Chart('Average organism\'s changes (Mutations)', Config.charts.changes), fit : new Chart('Average organism\'s Fitness', Config.charts.fit), age : new Chart('Average organism\'s Age', Config.charts.age), @@ -62,7 +62,7 @@ class Charts extends Status { * @override */ onStatus(status, orgs) { - //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${paenergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${penergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); // TODO: this code should be moved to separate plugin // TODO: add energy, orgs and code: e:xxx, o:xxx, c:xxx //const active = man.activeAround; diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 1b5884c..4232dfa 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -21,8 +21,8 @@ const Config = { killout : {pos: 'topright', active: false, transparent: 0.6}, orgs : {pos: '0-0|16', active: true, transparent: 0.6}, energy : {pos: '0-1|16', active: true, transparent: 0.6}, - paenergy : {pos: '0-2|16', active: true, transparent: 0.6}, - penergy : {pos: '0-3|16', active: true, transparent: 0.6}, + penergy : {pos: '0-2|16', active: true, transparent: 0.6}, + eenergy : {pos: '0-3|16', active: true, transparent: 0.6}, fit : {pos: '1-0|16', active: true, transparent: 0.6}, age : {pos: '1-1|16', active: true, transparent: 0.6}, code : {pos: '1-2|16', active: true, transparent: 0.6}, diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index c884ca0..c67e8cf 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -50,8 +50,8 @@ class Console extends Status { const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); const senergy = format(status.energy, 'nrg', 14); - const spaenergy = format(status.paenergy, 'anrg', 15); const spenergy = format(status.penergy, 'pnrg', 15); + const seenergy = format(status.eenergy, 'pnrg', 15); const skill = format(status.kill, 'kil', 14); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); @@ -59,7 +59,7 @@ class Console extends Status { const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spaenergy}${spenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } From bd8fa604f9537b8c0a683b43b526099a8520779d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 01:04:43 +0200 Subject: [PATCH 132/291] never mind... --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/status/console/Console.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 126bcf7..1d098a5 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -66,7 +66,7 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 50, + orgTournamentPeriod: 20, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index c67e8cf..d972661 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -52,7 +52,7 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 14); const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'pnrg', 15); - const skill = format(status.kill, 'kil', 14); + const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); const sage = format(status.age, 'age', 11); From f5619bbecabc13ad31492ca24b95f7a12cae294c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 02:17:35 +0200 Subject: [PATCH 133/291] cyclical mode in default config --- client/src/manager/plugins/organisms/Config.js | 14 +++++++------- client/src/manager/plugins/organisms/Organism.js | 3 ++- .../src/manager/plugins/organisms/dos/Organisms.js | 2 ++ client/src/manager/plugins/status/Status.js | 2 +- .../src/manager/plugins/status/console/Console.js | 2 +- client/src/share/Config.js | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 1d098a5..32c13a9 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -59,7 +59,7 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 200, + orgCrossoverPeriod: 0, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This @@ -71,7 +71,7 @@ const Config = { * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 200, + orgRandomOrgPeriod: 0, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -92,7 +92,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 30000, + orgAlivePeriod: 50000, /** * {Number} This value means the period between organism codeSizes, which * affects energy grabbing by the system. For example: we have two @@ -105,7 +105,7 @@ const Config = { * be grabbed from you. If your size is between 21-40, then 2 units of * energy will be grabbed from you and so on... */ - orgGarbagePeriod: 10, + orgGarbagePeriod: 7, /** * {Number} Size of organism stack (internal memory) */ @@ -134,7 +134,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 800, + orgMaxOrgs: 1000, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, @@ -142,11 +142,11 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 50, + codeMaxSize: 40, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 800, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 587e9ec..e12c37f 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -101,6 +101,7 @@ class Organism extends Observer { set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} set energy(e) {this._energy = e} + set startEnergy(e) {this._startEnergy = e} set changes(c) {this._updateColor(this._changes = c)} /** @@ -191,7 +192,7 @@ class Organism extends Observer { } fitness() { - return (OConfig.codeMaxSize - this.vm.size) * this._energy * (this._changes || 1); + return (OConfig.codeMaxSize - this.vm.size) * (this._energy - this.startEnergy) * (this._changes || 1); } destroy() { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 6046b38..283b9fa 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -80,6 +80,8 @@ class Organisms extends BaseOrganisms { org.grabEnergy(energy); childEnergy <= (childEnergy - energy) && this.parent.fire(EVENTS.KILL_CLONE, child); child.grabEnergy(childEnergy - energy); + org.alive && (org.startEnergy = org.energy); + child.alive && (child.startEnergy = child.energy); } addOrgHandlers(org) { diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 4f0fca1..7f8da3f 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -173,7 +173,7 @@ class Status extends Configurable { status.energy = fix(this._energy, 2); status.penergy = fix(this._pickEnergy, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); - status.changes = fix(this._changes, 2); + status.changes = +(this._changes).toFixed(1); status.fit = fix(this._fitness / 10000000, 2); status.age = fix(this._age / (this._ageCount || 1), 2); status.code = +(this._codeSize / orgAmount).toFixed(2); diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index d972661..ff18b79 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -51,7 +51,7 @@ class Console extends Status { const sorgs = format(orgs, 'org', 10); const senergy = format(status.energy, 'nrg', 14); const spenergy = format(status.penergy, 'pnrg', 15); - const seenergy = format(status.eenergy, 'pnrg', 15); + const seenergy = format(status.eenergy, 'enrg', 15); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index c78e429..5ce174e 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -58,7 +58,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... From 4a5330962f5ca74a4cb7ae55a6bfdad7cef0e32f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 18:35:21 +0200 Subject: [PATCH 134/291] temp commit. to sync other devices --- client/src/manager/plugins/ips/Config.js | 4 +- client/src/manager/plugins/ips/Ips.js | 7 +-- .../src/manager/plugins/organisms/Config.js | 8 +-- .../src/manager/plugins/organisms/Mutator.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 6 +- .../manager/plugins/organisms/Organisms.js | 14 ++++- client/src/manager/plugins/status/Status.js | 59 ++++++++----------- .../manager/plugins/status/charts/Charts.js | 13 ++-- .../manager/plugins/status/charts/Config.js | 1 - .../manager/plugins/status/console/Console.js | 13 ++-- client/src/share/Config.js | 2 +- client/src/share/Events.js | 2 +- 12 files changed, 61 insertions(+), 70 deletions(-) diff --git a/client/src/manager/plugins/ips/Config.js b/client/src/manager/plugins/ips/Config.js index a9e6a20..a57def9 100644 --- a/client/src/manager/plugins/ips/Config.js +++ b/client/src/manager/plugins/ips/Config.js @@ -5,11 +5,11 @@ */ const Config = { /** - * {Boolean} Shows/Hides IPS value on the left top corner of a canvas + * {Boolean} Shows/Hides title values on the left top corner of a canvas */ show : true, /** - * {Number} Period in milliseconds, which is used to update IPS + * {Number} Period in milliseconds, which is used to update titles */ periodMs: 1000 }; diff --git a/client/src/manager/plugins/ips/Ips.js b/client/src/manager/plugins/ips/Ips.js index 302a25e..970140e 100644 --- a/client/src/manager/plugins/ips/Ips.js +++ b/client/src/manager/plugins/ips/Ips.js @@ -13,7 +13,6 @@ const Configurable = require('./../../../../../common/src/Configurable'); const Helper = require('./../../../../../common/src/Helper'); const Config = require('./../../../share/Config').Config; -const EVENTS = require('./../../../share/Events').EVENTS; const IpsConfig = require('./Config'); class Ips extends Configurable { @@ -36,10 +35,10 @@ class Ips extends Configurable { const ts = stamp - this._stamp; if (ts < this.cfg.periodMs) {return} const man = this.parent; - let ips = man.codeRuns / (man.organisms.size || 1) / (ts / 1000); + //let ips = man.codeRuns / (man.organisms.size || 1) / (ts / 1000); - man.fire(EVENTS.IPS, ips, man.organisms); - man.codeRuns = 0; + //man.fire(EVENTS.IPS, ips, man.organisms); + //man.codeRuns = 0; this._stamp = stamp; } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 32c13a9..a040802 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -59,19 +59,19 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 100, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 20, + orgTournamentPeriod: 100, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 0, + orgRandomOrgPeriod: 100, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -134,7 +134,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 600, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index a69b4e0..7e46672 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -112,7 +112,7 @@ class Mutator { Mutator._onCopy ]; - manager.on(EVENTS.ORGANISM, this._onOrganism.bind(this)); + manager.on(EVENTS.CODE_RUN, this._onOrganism.bind(this)); manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index e12c37f..cb3b41e 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -16,12 +16,14 @@ const DESTROY = 1; const CLONE = 2; const KILL_NO_ENERGY = 3; const KILL_AGE = 4; +const ITERATION = 5; const ORG_EVENTS = { GRAB_ENERGY, DESTROY, CLONE, KILL_NO_ENERGY, - KILL_AGE + KILL_AGE, + ITERATION }; const IS_NUM = Helper.isNumeric; @@ -115,7 +117,7 @@ class Organism extends Observer { this.onRun(); if (this.alive) { - this.vm.size === 0 && this._onCodeEnd(this, 0); + this.vm.size > 0 && this.fire(ITERATION, this); this.alive && this._updateClone(); this.alive && this._updateAge(); this.alive && this._updateEnergy(); diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 3b6a5bb..470206b 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -117,6 +117,7 @@ class Organisms extends Configurable { org.on(ORG_EVENTS.CLONE, this._onCloneOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); + org.on(ORG_EVENTS.ITERATION, this._onIterationOrg.bind(this)); } reset() { @@ -269,13 +270,20 @@ class Organisms extends Configurable { _onKillNoEnergyOrg(org) {this._parent.fire(EVENTS.KILL_NO_ENERGY, org)} _onKillAgeOrg(org) {this._parent.fire(EVENTS.KILL_AGE, org)} + _onIterationOrg(org) { + this._parent.codeRuns += OConfig.codeYieldPeriod; + this._parent.fire(EVENTS.CODE_RUN, org); + } _updateCrossover(counter) { const orgAmount = this.organisms.size; if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} - - let org1 = this._tournament(); - let org2 = this._tournament(); + // + // We have to have a possibility to crossover not only with best + // organisms, but with low fit also + // + let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); + let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 7f8da3f..0e3ab10 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -1,11 +1,9 @@ /** * Base class for plugin which collects real time data about system like: - * population energy, changes, organisms ips etc and provide this data to + * population energy, changes, organisms lps etc and provide this data to * other visualization classes (e.g. Charts). Output data is an object of * described below format: * - * ips: Iterations Per Second - amount of all organisms full - * code runs per one second * lps: Lines Per Second - average amount of run code lines * per one second * org: Average amount of organisms at the moment of logging @@ -37,9 +35,8 @@ class Status extends Configurable { constructor(manager, statCfg, apiCfg = {}) { super(manager, {Config, cfg: statCfg}, apiCfg); - this.manager = manager; this._status = { - ips :0, lps :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age :0, code:0, + lps :0, orgs :0, energy :0, penergy:0, eenergy :0, changes:0, fit :0, age :0, code :0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killtour:0, killclone:0 }; this._stamp = 0; @@ -49,7 +46,7 @@ class Status extends Configurable { this._fitness = 0; this._changes = 0; this._codeSize = 0; - this._runLines = 1; + this._runLines = 0; this._age = 0; this._ageCount = 0; this._times = 0; @@ -57,8 +54,7 @@ class Status extends Configurable { this._statusCfg = statCfg; this._firstCall = true; - this._onIpsCb = this._onIps.bind(this); - this._onOrganismCb = this._onOrganism.bind(this); + this._onLoopCb = this._onLoop.bind(this); this._onEatEnergyCb = this._onEatEnergy.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); @@ -70,8 +66,7 @@ class Status extends Configurable { this._onKillTourCb = this._onKillHandlerOrg.bind(this, 7); this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); - manager.on(EVENTS.IPS, this._onIpsCb); - manager.on(EVENTS.ORGANISM, this._onOrganismCb); + manager.on(EVENTS.LOOP, this._onLoopCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); @@ -87,7 +82,7 @@ class Status extends Configurable { } destroy() { - const man = this.manager; + const man = this.parent; man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); man.off(EVENTS.KILL_TOUR, this._onKillTourCb); @@ -99,11 +94,9 @@ class Status extends Configurable { man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); - man.off(EVENTS.ORGANISM, this._onOrganismCb); - man.off(EVENTS.IPS, this._onIpsCb); + man.off(EVENTS.LOOP, this._onLoopCb); this._onKillOrgCb = null; - this._onOrganismCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; this._onKillTourCb = null; @@ -113,13 +106,12 @@ class Status extends Configurable { this._onKillEatCb = null; this._onKillAgeCb = null; this._onKillEnergyCb = null; - this._onIpsCb = null; + this._onLoopCb = null; this._status = null; this._statusCfg = null; - this.manager = null; } - onBeforeStatus(ips, orgs) { + _onBeforeLoop(orgs) { const size = orgs.size || 1; let energy = 0; let startEnergy = 0; @@ -145,30 +137,19 @@ class Status extends Configurable { this._codeSize = codeSize; } - onAfterStatus(stamp) { - this._times = 0; - this._runLines = 0; - this._age = 0; - this._ageCount = 0; - this._eatEnergy = 0; - this._pickEnergy = 0; - this._stamp = stamp; - _fill(this._kill, 0); - } - - _onIps(ips, orgs) { + _onLoop() { if (!this._statusCfg.active) {return} this._times++; const stamp = Date.now(); if (stamp - this._stamp < this._statusCfg.period) {return} + const orgs = this.parent.organisms; const status = this._status; const orgAmount = orgs.size || 1; const fix = Status._toFixed; - this.onBeforeStatus(ips, orgs); + this._onBeforeLoop(orgs); - status.ips = fix(ips, 2); - status.lps = fix(this._runLines / this._times, 0); + status.lps = fix(this.parent.codeRuns - this._runLines, 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); status.penergy = fix(this._pickEnergy, 2); @@ -188,13 +169,19 @@ class Status extends Configurable { status.killclone = fix(this._kill[8], 2); !this._firstCall && this.onStatus(status, orgs.size); - this.onAfterStatus(stamp); + this._onAfterLoop(stamp); this._firstCall = false; } - _onOrganism(org, lines) { - if (!this._statusCfg.active) {return} - this._runLines += lines; + _onAfterLoop(stamp) { + this._times = 0; + this._runLines = this.parent.codeRuns; + this._age = 0; + this._ageCount = 0; + this._eatEnergy = 0; + this._pickEnergy = 0; + this._stamp = stamp; + _fill(this._kill, 0); } /** diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index f02891b..05b6bc6 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -25,7 +25,6 @@ class Charts extends Status { this._data = new Array(2); this._charts = { - ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), lps : new Chart('LPS - Lines Per Second', Config.charts.lps), orgs : new Chart('Amount of organisms', Config.charts.orgs), energy : new Chart('Average organism energy', Config.charts.energy), @@ -62,11 +61,11 @@ class Charts extends Status { * @override */ onStatus(status, orgs) { - //console.log(`%c${conns}${sips}${slps}${sorgs}%c${siq}${penergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + //console.log(`%c${conns}${slps}${sorgs}%c${siq}${penergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); // TODO: this code should be moved to separate plugin // TODO: add energy, orgs and code: e:xxx, o:xxx, c:xxx //const active = man.activeAround; - //man.canvas && man.canvas.text(5, 20, `${sips}${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); + //man.canvas && man.canvas.text(5, 20, `${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); const data = this._data; @@ -92,7 +91,7 @@ class Charts extends Status { /** * Sets specified chart transparent coefficient. May be called * with one Number parameter to set it for all charts. - * @param {String|Number} chart Chart name, e.g: 'energy', or 'ips' or opacity value + * @param {String|Number} chart Chart name, e.g: 'energy', or 'lps' or opacity value * @param {Number=} t Value between 0...1 or undefined * @api */ @@ -108,7 +107,7 @@ class Charts extends Status { * Sets current chart position. Available positions: * top, down, left, right, topleft, downleft, topright, * downright, full. - * @param {String} chart Chart name, e.g: 'energy', or 'ips' + * @param {String} chart Chart name, e.g: 'energy', or 'lps' * @param {String} p new position * @api */ @@ -120,7 +119,7 @@ class Charts extends Status { * downright, full. This method may be called with one * Boolean parameter. In this case all charts will be activated * or deactivated. - * @param {String|Boolean} chart Chart name, e.g: 'energy', or 'ips' + * @param {String|Boolean} chart Chart name, e.g: 'energy', or 'lps' * @param {Boolean=} a New active state * @api */ @@ -136,7 +135,7 @@ class Charts extends Status { * Resets chart data. It means, that chart will be refreshed with * data started from this moment and further. You may call this * method without parameters to reset all charts. - * @param {String=} chart Chart name, e.g: 'energy', or 'ips' + * @param {String=} chart Chart name, e.g: 'energy', or 'lps' * @api */ _reset(chart) { diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 4232dfa..f1e7733 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -16,7 +16,6 @@ const Config = { * {Object} Available chart types */ charts: { - ips : {pos: 'topleft', active: false, transparent: 0.6}, lps : {pos: 'downleft', active: false, transparent: 0.6}, killout : {pos: 'topright', active: false, transparent: 0.6}, orgs : {pos: '0-0|16', active: true, transparent: 0.6}, diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index ff18b79..e28a97a 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -1,11 +1,9 @@ /** * This plugin is a primitive version of real time charts. It shows * different parameters of the jevo.js system, like average energy, - * ips (Iterations Per Second), average code size and so on. Here + * lps (Lines Per Second), average code size and so on. Here * labels explanation: * - * ips: Iterations Per Second - amount of all organisms full - * code runs per one second * lps: Lines Per Second - average amount of run code lines * per one second * org: Average amount of organisms at the moment of logging @@ -46,12 +44,11 @@ class Console extends Status { const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; const conns = `con:${con === ' ' ? 'no ' : con}`; - const sips = format(status.ips, 'ips', 10); const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); - const senergy = format(status.energy, 'nrg', 14); - const spenergy = format(status.penergy, 'pnrg', 15); - const seenergy = format(status.eenergy, 'enrg', 15); + const senergy = format(status.energy, 'nrg', 17); + const spenergy = format(status.penergy, 'pnrg', 17); + const seenergy = format(status.eenergy, 'enrg', 16); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); @@ -59,7 +56,7 @@ class Console extends Status { const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 5ce174e..577c4c8 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -82,7 +82,7 @@ ClientConfig.init({ * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 5000, + worldEnergyCheckPeriod: 1000, /** * {Boolean} Turns on/off scroll bars in a 2D canvas */ diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 2181437..320e979 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -9,7 +9,7 @@ const EVENTS = { ITERATION : 0, LOOP : 1, - IPS : 2, + CODE_RUN : 2, BACKUP : 3, ORGANISM : 4, GRAB_ENERGY : 5, From b20801836982b641ad9bd0d0272c9a4cf502c4df Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 18:41:58 +0200 Subject: [PATCH 135/291] . --- client/src/manager/plugins/organisms/Organism.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 4ff8537..1f1d12d 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -181,7 +181,7 @@ class Organism extends Observer { } fitness() { - return (OConfig.codeMaxSize - this.vm.size) * this._energy * (this._changes || 1); + return (OConfig.codeMaxSize + 1 - this.vm.size) * this._energy * (this._changes || 1); } destroy() { From c0a721feb07930691742ce2b7c3a8b3ad138aa64 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 17 Jan 2018 21:30:19 +0200 Subject: [PATCH 136/291] working on real time mutations adding --- .../src/manager/plugins/organisms/Mutator.js | 15 ++++-- .../src/manager/plugins/organisms/Organism.js | 12 ++--- .../manager/plugins/organisms/Organisms.js | 13 ++--- .../manager/plugins/organisms/dos/Organism.js | 6 +-- .../plugins/organisms/garmin/Organism.js | 6 +-- client/src/manager/plugins/status/Status.js | 1 + .../manager/plugins/status/console/Console.js | 2 +- client/src/share/Events.js | 53 +++++++++---------- client/src/vm/VM.js | 10 +--- 9 files changed, 52 insertions(+), 66 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 7e46672..c840095 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -111,17 +111,24 @@ class Mutator { Mutator._onAdd, Mutator._onCopy ]; - - manager.on(EVENTS.CODE_RUN, this._onOrganism.bind(this)); - manager.on(EVENTS.CLONE, this._onCloneOrg.bind(this)); + + this._onOrganismCb = this._onOrganism.bind(this); + this._onCloneCb = this._onCloneOrg.bind(this); + + manager.on(EVENTS.CODE_RUN, this._onOrganismCb); + manager.on(EVENTS.CLONE, this._onCloneCb); } destroy() { + this._manager.on(EVENTS.CLONE, this._onCloneCb); + this._manager.on(EVENTS.CODE_RUN, this._onOrganismCb); + this._onCloneCb = null; + this._onOrganismCb = null; this._manager = null; this._MUTATION_TYPES = null; } - _onOrganism(org) { + _onOrganism(lines, org) { if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && OConfig.orgRainMutationPercent > 0.0 && org.mutationPeriod > 0 && org.alive) { this._mutate(org, false); } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index c6defec..4bc493e 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -52,15 +52,12 @@ class Organism extends Observer { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Function} onCodeEnd Callback, which is called at the - * end of every code iteration. * @param {Function} operatorCls Class of operators * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, onCodeEnd, operatorCls, parent = null) { + constructor(id, x, y, alive, item, operatorCls, parent = null) { super(EVENT_AMOUNT); - this._onCodeEnd = onCodeEnd; this._operatorCls = operatorCls; if (parent === null) {this._create()} @@ -117,7 +114,7 @@ class Organism extends Observer { this.onRun(); if (this.alive) { - this.vm.size > 0 && this.fire(ITERATION, this); + this.fire(ITERATION, this.vm.size > 0 ? OConfig.codeYieldPeriod : 0, this); this.alive && this._updateClone(); this.alive && this._updateAge(); this.alive && this._updateEnergy(); @@ -207,14 +204,13 @@ class Organism extends Observer { this._mutationProbs = null; this.vm && this.vm.destroy(); this.vm = null; - this._onCodeEnd = null; this._operatorCls = null; super.destroy(); } _create() { - this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls); + this.vm = new VM(this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; this._color = OConfig.orgStartColor; @@ -228,7 +224,7 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this._onCodeEnd.bind(this, this), this, this._operatorCls, parent.vm); + this.vm = new VM(this, this._operatorCls, parent.vm); this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 470206b..389a022 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -141,7 +141,7 @@ class Organisms extends Configurable { if (pos === false) {return false} orgs.add(null); let last = orgs.last; - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, this._onCodeEnd.bind(this), parent); + let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, parent); last.val = org; this.addOrgHandlers(org); @@ -246,11 +246,6 @@ class Organisms extends Configurable { return this.parent.organisms.size; } - _onCodeEnd(org, lines) { - this.parent.codeRuns++; - this.parent.fire(EVENTS.ORGANISM, org, lines); - } - _onKillOrg(org) { if (this.randOrgItem === org.item) { if ((this.randOrgItem = org.item.next) === null) { @@ -270,9 +265,9 @@ class Organisms extends Configurable { _onKillNoEnergyOrg(org) {this._parent.fire(EVENTS.KILL_NO_ENERGY, org)} _onKillAgeOrg(org) {this._parent.fire(EVENTS.KILL_AGE, org)} - _onIterationOrg(org) { - this._parent.codeRuns += OConfig.codeYieldPeriod; - this._parent.fire(EVENTS.CODE_RUN, org); + _onIterationOrg(lines, org) { + this._parent.codeRuns += lines; + this._parent.fire(EVENTS.CODE_RUN, lines, org); } _updateCrossover(counter) { diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 6dc5f7b..4478e9b 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -17,12 +17,10 @@ class OrganismDos extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Function} codeEndCb Callback, which is called at the - * end of every code iteration. * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, codeEndCb, parent = null) { - super(id, x, y, alive, item, codeEndCb, Operators, parent); + constructor(id, x, y, alive, item, parent = null) { + super(id, x, y, alive, item, Operators, parent); } onRun() { diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index b422dc8..deab6a7 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -20,12 +20,10 @@ class OrganismGarmin extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Function} codeEndCb Callback, which is called at the - * end of every code iteration. * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, codeEndCb, parent = null) { - super(id, x, y, alive, item, codeEndCb, Operators, parent); + constructor(id, x, y, alive, item, parent = null) { + super(id, x, y, alive, item, Operators, parent); this._needRun = true; diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 0e3ab10..34f7c34 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -158,6 +158,7 @@ class Status extends Configurable { status.fit = fix(this._fitness / 10000000, 2); status.age = fix(this._age / (this._ageCount || 1), 2); status.code = +(this._codeSize / orgAmount).toFixed(2); + status.kill = fix(this._kill[0], 2); status.killenergy = fix(this._kill[1], 2); status.killage = fix(this._kill[2], 2); diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index e28a97a..3e3353f 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -38,7 +38,7 @@ class Console extends Status { * @override */ onStatus(status, orgs) { - const man = this.manager; + const man = this.parent; const active = man.activeAround; const format = Console._format; diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 320e979..cc456e5 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -11,33 +11,32 @@ const EVENTS = { LOOP : 1, CODE_RUN : 2, BACKUP : 3, - ORGANISM : 4, - GRAB_ENERGY : 5, - UPDATE_ENERGY : 6, - KILL : 7, // general kill event - KILL_NO_ENERGY : 8, // killed if zero energy - KILL_AGE : 9, // killed if max age reached - KILL_EAT : 10, // killed, because other organism has eat this one - KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 12, // killed, because organism step outside the world - KILL_STEP_IN : 13, // killed, because of panishment for step in from near client - KILL_TOUR : 14, // killed in tournament - KILL_CLONE : 15, // killed, because of lack of energy after clone - MUTATIONS : 16, - CLONE : 17, - EAT : 18, - EAT_ORG : 19, - EAT_ENERGY : 20, - STEP : 21, - STEP_OUT : 22, - STEP_IN : 23, - BORN_ORGANISM : 24, - GET_ENERGY : 25, - DESTROY : 26, - RUN : 27, - STOP : 28, - RESET_CODE : 29, - CHECK_AT : 30 + GRAB_ENERGY : 4, + UPDATE_ENERGY : 5, + KILL : 6, // general kill event + KILL_NO_ENERGY : 7, // killed if zero energy + KILL_AGE : 8, // killed if max age reached + KILL_EAT : 9, // killed, because other organism has eat this one + KILL_OVERFLOW : 10, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 11, // killed, because organism step outside the world + KILL_STEP_IN : 12, // killed, because of panishment for step in from near client + KILL_TOUR : 13, // killed in tournament + KILL_CLONE : 14, // killed, because of lack of energy after clone + MUTATIONS : 15, + CLONE : 16, + EAT : 17, + EAT_ORG : 18, + EAT_ENERGY : 19, + STEP : 20, + STEP_OUT : 21, + STEP_IN : 22, + BORN_ORGANISM : 23, + GET_ENERGY : 24, + DESTROY : 25, + RUN : 26, + STOP : 27, + RESET_CODE : 28, + CHECK_AT : 29 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 69482af..84ea9c3 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -28,12 +28,11 @@ class VM extends Observer { * Creates VM instance. codeEndCb will be called after last code line is run. * parent is used if VM instance is in a cloning mode and we have to create * a copy of it. - * @param {Function} codeEndCb * @param {Observer} obs Observer instance for Operators class * @param {Function} operatorCls Class of operators * @param {VM} parent Parent VM instance in case of cloning */ - constructor(codeEndCb, obs, operatorCls, parent = null) { + constructor(obs, operatorCls, parent = null) { super(EVENT_AMOUNT); this._obs = obs; @@ -42,11 +41,6 @@ class VM extends Observer { * script parts for current VM instance */ this._operatorCls = operatorCls; - /** - * {Function} Callback, which is called on every organism - * vm iteration. On it's end. - */ - this._onCodeEnd = codeEndCb; /** * {Array} Array of two numbers. first - line number where we have * to return if first line appears. second - line number, where ends @@ -112,7 +106,6 @@ class VM extends Observer { if (line >= lines && org.alive) { line = 0; this._operators.offsets = this._offsets = []; - this._onCodeEnd(len2 - len); len2 = len; continue; } @@ -136,7 +129,6 @@ class VM extends Observer { this._offsets = null; this._vars = null; this._code = null; - this._onCodeEnd = null; this._obs = null; this._ops = null; From c3a911f0bf49504d5b581e3672ab834f08df587e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 18 Jan 2018 01:50:57 +0200 Subject: [PATCH 137/291] a lot of small speed optimizations working on problem of local optima fixed an issue of inefficient random organisms changed checkXXX() methods. from now, they return amount of energy improved charts API --- client/src/manager/plugins/organisms/Config.js | 6 +++--- client/src/manager/plugins/organisms/Mutator.js | 16 +++++++++------- client/src/manager/plugins/organisms/Organism.js | 10 +++++----- .../src/manager/plugins/organisms/Organisms.js | 13 ++++++++++--- .../manager/plugins/organisms/dos/Organisms.js | 14 +++----------- .../plugins/organisms/garmin/Organisms.js | 1 - client/src/manager/plugins/status/Status.js | 11 ++++++----- .../src/manager/plugins/status/charts/Charts.js | 2 +- client/src/vm/VM.js | 6 +++--- 9 files changed, 40 insertions(+), 39 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index a040802..b18f50a 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -66,7 +66,7 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 100, + orgTournamentPeriod: 50, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature @@ -82,7 +82,7 @@ const Config = { * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.0, + orgRainMutationPercent: 0.1, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -146,7 +146,7 @@ const Config = { /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 1000, + orgStartAmount: 600, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index c840095..47c9e6f 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -96,8 +96,9 @@ class Mutator { org.changes += (org.vm.copyLines() * MAX_BITS); } - constructor(manager) { + constructor(manager, owner) { this._manager = manager; + this._owner = owner; this._MUTATION_TYPES = [ Mutator._onChange, Mutator._onDel, @@ -115,20 +116,21 @@ class Mutator { this._onOrganismCb = this._onOrganism.bind(this); this._onCloneCb = this._onCloneOrg.bind(this); - manager.on(EVENTS.CODE_RUN, this._onOrganismCb); - manager.on(EVENTS.CLONE, this._onCloneCb); + Helper.override(owner, 'onOrganism', this._onOrganismCb); + Helper.override(owner, 'onClone', this._onCloneCb); } destroy() { - this._manager.on(EVENTS.CLONE, this._onCloneCb); - this._manager.on(EVENTS.CODE_RUN, this._onOrganismCb); + Helper.unoverride(this._owner, 'onClone', this._onCloneCb); + Helper.unoverride(this._owner, 'onOrganism', this._onOrganismCb); this._onCloneCb = null; this._onOrganismCb = null; this._manager = null; + this._owner = null; this._MUTATION_TYPES = null; } - _onOrganism(lines, org) { + _onOrganism(org) { if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && OConfig.orgRainMutationPercent > 0.0 && org.mutationPeriod > 0 && org.alive) { this._mutate(org, false); } @@ -145,7 +147,7 @@ class Mutator { * @param {Boolean} clone true if mutation is applying after clone */ _mutate(org, clone = true) { - const vm = org.vm; + const vm = org.vm; const probIndex = Helper.probIndex; const mTypes = this._MUTATION_TYPES; const maxSize = OConfig.codeMaxSize; diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 4bc493e..4e97cb7 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -113,11 +113,11 @@ class Organism extends Observer { if (this.onBeforeRun() === false) {return true} this.onRun(); - if (this.alive) { + if (this._alive) { this.fire(ITERATION, this.vm.size > 0 ? OConfig.codeYieldPeriod : 0, this); - this.alive && this._updateClone(); - this.alive && this._updateAge(); - this.alive && this._updateEnergy(); + this._alive && this._updateClone(); + this._alive && this._updateAge(); + this._alive && this._updateEnergy(); } return true; @@ -191,7 +191,7 @@ class Organism extends Observer { } fitness() { - return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this.startEnergy) * (this._changes || 1); + return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); } destroy() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 389a022..e779912 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -88,7 +88,7 @@ class Organisms extends Configurable { this.positions = manager.positions; this.world = manager.world; - this._mutator = new Mutator(manager); + this._mutator = new Mutator(manager, this); this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -186,8 +186,8 @@ class Organisms extends Configurable { } this._updateAmount(counter); - this._updateCrossover(counter); this._updateRandomOrgs(counter); + this._updateCrossover(counter); } _onLoop() { @@ -297,7 +297,14 @@ class Organisms extends Configurable { const newOrg = this.organisms.last.val; const vm = newOrg.vm; if (org === newOrg) {return false} - + // + // IMPORTANT! This line reset energy for new/created organism. + // With low energy, organism will not have a chance to survive + // and have a ancestors. So, there is some probability, that + // source organism will have high amount of energy and therefore + // high chances to survive + // + newOrg.energy = org.energy; vm.generate(org.vm.size); if ((orgAmount + 1) > OConfig.orgMaxOrgs) { this.parent.fire(EVENTS.KILL_OVERFLOW, org); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 283b9fa..4a648fd 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -4,7 +4,6 @@ * * Events od Manager: * TODO: - * ORGANISM(org) Fires after one organism has processed * * Depends on: * manager/Manager @@ -19,10 +18,6 @@ const EVENTS = require('./../../../../share/Events').EVENTS; const Helper = require('./../../../../../../common/src/Helper'); const DIR = require('./../../../../../../common/src/Directions').DIR; -const EMPTY = 0; -const ENERGY = 1; -const ORGANISM = 2; - class Organisms extends BaseOrganisms { constructor(manager) { super(manager); @@ -243,14 +238,11 @@ class Organisms extends BaseOrganisms { } _onCheckAt(x, y, ret) { - let dir; + const org = this.positions[Helper.posId(x, y)]; + let dir; [x, y, dir] = Helper.normalize(x, y); - if (typeof(this.positions[Helper.posId(x, y)]) === 'undefined') { - ret.ret = this.world.getDot(x, y) > 0 ? ENERGY : EMPTY; - } else { - ret.ret = ORGANISM; - } + ret.ret = typeof(org) === 'undefined' ? this.world.getDot(x, y) : org.energy; } } diff --git a/client/src/manager/plugins/organisms/garmin/Organisms.js b/client/src/manager/plugins/organisms/garmin/Organisms.js index 0624e43..a484bd4 100644 --- a/client/src/manager/plugins/organisms/garmin/Organisms.js +++ b/client/src/manager/plugins/organisms/garmin/Organisms.js @@ -3,7 +3,6 @@ * in fitness mode. * * Events od Manager: - * ORGANISM(org) Fires after one organism has processed * * Depends on: * manager/Manager diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 34f7c34..f3669b8 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -15,6 +15,7 @@ * @author flatline */ const _fill = require('lodash/fill'); +const Helper = require('./../../../../../common/src/Helper'); const EVENTS = require('./../../../share/Events').EVENTS; const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; @@ -66,7 +67,7 @@ class Status extends Configurable { this._onKillTourCb = this._onKillHandlerOrg.bind(this, 7); this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); - manager.on(EVENTS.LOOP, this._onLoopCb); + Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); @@ -94,7 +95,7 @@ class Status extends Configurable { man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); - man.off(EVENTS.LOOP, this._onLoopCb); + Helper.unoverride(manager, 'onLoop', this._onLoopCb); this._onKillOrgCb = null; this._onEatEnergyCb = null; @@ -149,7 +150,7 @@ class Status extends Configurable { this._onBeforeLoop(orgs); - status.lps = fix(this.parent.codeRuns - this._runLines, 0); + status.lps = fix((this.parent.codeRuns - this._runLines) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); status.penergy = fix(this._pickEnergy, 2); @@ -195,9 +196,9 @@ class Status extends Configurable { _onKillOrg(org) { if (!this._statusCfg.active) {return} - this._age += org.iterations; - this._kill[0]++; + this._age += org.iterations; this._ageCount++; + this._kill[0] ++; } _onKillHandlerOrg(index) { diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 05b6bc6..11684c6 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -125,7 +125,7 @@ class Charts extends Status { */ _active(chart, a) { if (typeof a === 'undefined') { - _each(this._charts, (c, k) => this._setProperty(k, 'active', chart)); + _each(this._charts, (c, k) => this._setProperty(k, 'active', typeof chart === 'undefined' ? true : chart)); } else { this._setProperty(chart, 'active', a); } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 84ea9c3..e7d468a 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -25,9 +25,8 @@ const VAR_BITS_OFFS = Num.VAR_BITS_OFFS; class VM extends Observer { /** - * Creates VM instance. codeEndCb will be called after last code line is run. - * parent is used if VM instance is in a cloning mode and we have to create - * a copy of it. + * Creates VM instance. parent is used if VM instance is in a + * cloning mode and we have to create a copy of it. * @param {Observer} obs Observer instance for Operators class * @param {Function} operatorCls Class of operators * @param {VM} parent Parent VM instance in case of cloning @@ -243,6 +242,7 @@ class VM extends Observer { const code = this._code = new Array(size); for (let i = 0; i < size; i++) {code[i] = Num.get()} + this._reset(); } _reset() { From 0c1c5b47a43ad48eaa56d0e5c9407c6b9451ddf6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 19 Jan 2018 01:01:40 +0200 Subject: [PATCH 138/291] returned IPS parameter (added chart) added configs: orgClonePerOrg, orgRainPerOrg to prevent organisms change rain and clone mutations changed basic mechanism of fitness calculating changed memory access logic fixed few issues related to vars amount fixed Code2String condition and memory translation from now VM.run() returns amount of run lines added cutting of start data for charts on overflow fixed man.api.charts.active() API optimized VM main loop --- client/src/manager/plugins/ips/Ips.js | 24 ++++-- .../src/manager/plugins/organisms/Config.js | 82 ++++++++++-------- .../src/manager/plugins/organisms/Mutator.js | 25 +++--- .../src/manager/plugins/organisms/Organism.js | 10 ++- .../manager/plugins/organisms/Organisms.js | 85 ++++++++----------- .../plugins/organisms/dos/Code2String.js | 21 +++-- .../plugins/organisms/dos/Operators.js | 14 ++- .../manager/plugins/organisms/dos/Organism.js | 2 +- client/src/manager/plugins/status/Status.js | 22 ++++- .../manager/plugins/status/charts/Chart.js | 7 +- .../manager/plugins/status/charts/Charts.js | 12 ++- .../manager/plugins/status/charts/Config.js | 42 +++++---- .../manager/plugins/status/console/Console.js | 5 +- client/src/share/Events.js | 57 +++++++------ client/src/vm/VM.js | 39 +++++---- 15 files changed, 255 insertions(+), 192 deletions(-) diff --git a/client/src/manager/plugins/ips/Ips.js b/client/src/manager/plugins/ips/Ips.js index 970140e..f183eff 100644 --- a/client/src/manager/plugins/ips/Ips.js +++ b/client/src/manager/plugins/ips/Ips.js @@ -14,34 +14,40 @@ const Configurable = require('./../../../../../common/src/Configurable'); const Helper = require('./../../../../../common/src/Helper'); const Config = require('./../../../share/Config').Config; const IpsConfig = require('./Config'); +const EVENTS = require('./../../../share/Events').EVENTS; class Ips extends Configurable { constructor(manager) { super(manager, {Config, cfg: IpsConfig}, {show: ['_show', 'Shows IPS of the world']}); - this._stamp = Date.now(); - this._onLoopCb = this._onLoop.bind(this); + this._stamp = Date.now(); + this._ips = 0; + this._onLoopCb = this._onLoop.bind(this); + this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onLoop', this._onLoopCb); + Helper.override(manager, 'onIteration', this._onIterationCb); } destroy() { Helper.unoverride(this.parent, 'onLoop', this._onLoopCb); - this._onLoopCb = null; + Helper.unoverride(this.parent, 'onIteration', this._onIterationCb); + this._onLoopCb = null; + this._onIterationCb = null; super.destroy(); } _onLoop(counter, stamp) { if (!this.cfg.show) {return} - const ts = stamp - this._stamp; + const ts = stamp - this._stamp; if (ts < this.cfg.periodMs) {return} - const man = this.parent; - //let ips = man.codeRuns / (man.organisms.size || 1) / (ts / 1000); - //man.fire(EVENTS.IPS, ips, man.organisms); - //man.codeRuns = 0; - this._stamp = stamp; + this.parent.fire(EVENTS.IPS, this._ips / (ts / 1000)); + this._ips = 0; + this._stamp = stamp; } + _onIteration() {this._ips++} + _show(show = true) { this.cfg.show = show; } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index b18f50a..4e940d4 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -46,20 +46,48 @@ const Config = { * ] */ orgMutationProbs: [1,1,100,1,1,1,1,1,1,10,1], + /** + * {Number} Percent of energy, which will be given to the child. Set to 0.0 + * to share the same amount of energy with child (energy duplication) + */ + orgCloneEnergyPercent: 0.5, /** * {Number} Percent of mutations from vm size, which will be applied to * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ - orgCloneMutationPercent: 0.1, + orgCloneMutationPercent: 0.0, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ orgClonePeriod: 100, + /** + * {Boolean} Turn this flag on to give organism a possibility to choose his + * own clone period and percent. false - mean, that these values will be constant + * for all organisms + */ + orgClonePerOrg: false, + /** + * {Number} Amount of iterations within organism's life loop, after that we + * do mutations according to orgRainMutationPercent config. If 0, then + * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD + */ + orgRainMutationPeriod: 5000, + /** + * {Number} Percent of mutations from code size. 0 is a possible value if + * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) + */ + orgRainMutationPercent: 0.02, + /** + * {Boolean} Turn this flag on to give organism a possibility to choose his + * own mutations period and percent. false - mean, that these values will be + * constant for all organisms + */ + orgRainPerOrg: false, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 100, + orgCrossoverPeriod: 0, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This @@ -71,18 +99,7 @@ const Config = { * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 100, - /** - * {Number} Amount of iterations within organism's life loop, after that we - * do mutations according to orgRainMutationPercent config. If 0, then - * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD - */ - orgRainMutationPeriod: 0, - /** - * {Number} Percent of mutations from code size. 0 is a possible value if - * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) - */ - orgRainMutationPercent: 0.1, + orgRandomOrgPeriod: 2000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -110,11 +127,6 @@ const Config = { * {Number} Size of organism stack (internal memory) */ orgMemSize: 128, - /** - * {Number} Percent of energy, which will be given to the child. Set to 0.0 - * to share the same amount of energy with child (energy duplication) - */ - orgCloneEnergyPercent: 0.5, /** * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. @@ -134,19 +146,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 600, - /** - * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef - * will be used during it's energy grabbing by system. We use this approach, - * because our CPU's are slow and organisms with big codes are very slow. But - * it's possible for organisms to go outside the limit by inventing new - * effective mechanisms of energy obtaining. - */ - codeMaxSize: 40, + orgMaxOrgs: 300, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 600, + orgStartAmount: 300, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -158,11 +162,6 @@ const Config = { * should be set in HEX-RGB mode. Example: 0xRRGGBB */ orgStartColor: 0xFF0000, - /** - * {Number} Amount of bits per one variable. It affects maximum value, - * which this variable may contain. This value shouldn't be less then 2. - */ - codeBitsPerVar: 2, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is @@ -175,6 +174,11 @@ const Config = { * then codeMaxSize, then entire code of organism will be run */ codeYieldPeriod: 10, + /** + * {Number} Amount of bits per one variable. It affects maximum value, + * which this variable may contain. This value shouldn't be less then 2. + */ + codeBitsPerVar: 4, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. @@ -184,12 +188,20 @@ const Config = { * {Number} Amount of bits, which stores maximum block length. Under block * length we mean maximum amount of lines in one block like if, for,... */ - codeBitsPerBlock: 4, + codeBitsPerBlock: 8, /** * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ codeIterationsPerOnce: 200, + /** + * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef + * will be used during it's energy grabbing by system. We use this approach, + * because our CPU's are slow and organisms with big codes are very slow. But + * it's possible for organisms to go outside the limit by inventing new + * effective mechanisms of energy obtaining. + */ + codeMaxSize: 40 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 47c9e6f..a5d2b65 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -57,17 +57,14 @@ class Mutator { } } - static _onClone(org) { - org.cloneMutationPercent = Math.random(); - org.changes++; - } - - static _onPeriod(org) { + static _onMutationPeriod(org) { + if (!OConfig.orgRainPerOrg) {return} org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod); org.changes++; } - static _onAmount(org) { + static _onMutationPercent(org) { + if (!OConfig.orgRainPerOrg) {return} org.mutationPercent = Math.random(); org.changes++; } @@ -77,12 +74,20 @@ class Mutator { org.changes++; } + static _onClone(org) { + if (!OConfig.orgClonePerOrg) {return} + org.cloneMutationPercent = Math.random(); + org.changes++; + } + static _onCloneEnergyPercent(org) { + if (!OConfig.orgClonePerOrg) {return} org.cloneEnergyPercent = Math.random(); org.changes++; } static _onClonePeriod(org) { + if (!OConfig.orgClonePerOrg) {return} org.clonePeriod = Helper.rand(OConfig.ORG_MAX_CLONE_PERIOD); org.changes++; } @@ -103,10 +108,10 @@ class Mutator { Mutator._onChange, Mutator._onDel, Mutator._onSmallChange, - Mutator._onClone, - Mutator._onPeriod, - Mutator._onAmount, + Mutator._onMutationPeriod, + Mutator._onMutationPercent, Mutator._onProbs, + Mutator._onClone, Mutator._onCloneEnergyPercent, Mutator._onClonePeriod, Mutator._onAdd, diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 4e97cb7..85bc0d3 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -39,6 +39,7 @@ class Organism extends Observer { /** * Is called as a running body (main) method + * @return {Number} Amount of run lines * @abstract */ onRun() {} @@ -111,10 +112,10 @@ class Organism extends Observer { run() { this._iterations++; if (this.onBeforeRun() === false) {return true} - this.onRun(); + const lines = this.onRun(); + this.fire(ITERATION, lines, this); if (this._alive) { - this.fire(ITERATION, this.vm.size > 0 ? OConfig.codeYieldPeriod : 0, this); this._alive && this._updateClone(); this._alive && this._updateAge(); this._alive && this._updateEnergy(); @@ -191,7 +192,8 @@ class Organism extends Observer { } fitness() { - return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); + //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); + return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); } destroy() { @@ -220,7 +222,7 @@ class Organism extends Observer { this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; - this._mem = []; + this._mem = new Array(OConfig.orgMemSize); } _clone(parent) { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index e779912..ff62180 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -270,56 +270,6 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - _updateCrossover(counter) { - const orgAmount = this.organisms.size; - if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} - // - // We have to have a possibility to crossover not only with best - // organisms, but with low fit also - // - let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - - if (!org1.alive || !org2.alive) {return false} - this._crossover(org1, org2); - if ((orgAmount + 1) > OConfig.orgMaxOrgs) { - this.parent.fire(EVENTS.KILL_OVERFLOW, org1); - org1.destroy(); - } - - return true; - } - - _updateRandomOrgs(counter) { - const orgAmount = this.organisms.size; - if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || orgAmount < 1 || !this.createOrg(this.parent.world.getFreePos())) {return false} - const org = this.randOrg(); - const newOrg = this.organisms.last.val; - const vm = newOrg.vm; - if (org === newOrg) {return false} - // - // IMPORTANT! This line reset energy for new/created organism. - // With low energy, organism will not have a chance to survive - // and have a ancestors. So, there is some probability, that - // source organism will have high amount of energy and therefore - // high chances to survive - // - newOrg.energy = org.energy; - vm.generate(org.vm.size); - if ((orgAmount + 1) > OConfig.orgMaxOrgs) { - this.parent.fire(EVENTS.KILL_OVERFLOW, org); - org.destroy(); - } - - return true; - } - - _updateCreate() { - if (this.organisms.size < 1) { - this._createPopulation(); - } - } - /** * Does tournament between two random organisms and kill looser, if amount of * organisms is greater or equal to maximum (OConfig.orgMaxOrgs). In general @@ -344,6 +294,41 @@ class Organisms extends Configurable { return true; } + + _updateRandomOrgs(counter) { + if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || this.organisms.size < 1) {return false} + const vm = this.randOrg().vm; + const size = Helper.rand(vm.size) + 1; + const pos = Helper.rand(vm.size - size); + + vm.generate(pos, size); + + return true; + } + + _updateCrossover(counter) { + const orgAmount = this.organisms.size; + if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} + // + // We have to have a possibility to crossover not only with best + // organisms, but with low fit also + // + let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); + let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); + + if (!org1.alive || !org2.alive) {return false} + this._crossover(org1, org2); + if ((orgAmount + 1) > OConfig.orgMaxOrgs) { + this.parent.fire(EVENTS.KILL_OVERFLOW, org1); + org1.destroy(); + } + + return true; + } + + _updateCreate() { + if (this.organisms.size < 1) {this._createPopulation()} + } } module.exports = Organisms; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 662796d..2a9624d 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -5,8 +5,8 @@ * * @author flatline */ -const Num = require('./../../../../vm/Num'); - +const Num = require('./../../../../vm/Num'); +const OConfig = require('./../Config'); /** * {Function} Just a shortcuts */ @@ -14,7 +14,10 @@ const VAR0 = Num.getVar; const VAR1 = (n) => Num.getVar(n, 1); const VAR2 = (n) => Num.getVar(n, 2); const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; +const BLOCK_MAX_LEN = OConfig.codeBitsPerBlock; const BITS_FOR_NUMBER = 16; +const FOUR_BITS = 4; +const CONDITION_BITS = 2; const HALF_OF_VAR = Num.MAX_VAR / 2; class Code2String { @@ -145,20 +148,22 @@ class Code2String { // } _onCondition(num, line, lines) { - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); + const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); + this._offsets.push(this._getOffs(line, lines, val3)); - return `if(v${VAR0(num)}${this._CONDITIONS[VAR2(num)]}v${VAR1(num)}){`; + return `if(v${VAR0(num)}${this._CONDITIONS[cond]}v${VAR1(num)}){`; } _onLoop(num, line, lines) { const var0 = VAR0(num); - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); + const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); this._offsets.push(this._getOffs(line, lines, val3)); return `for(v${var0}=v${VAR1(num)};v${var0}= org.mem.length ? 0 : org.mem[index]; + return ++line; + } onToMem(num, line, org) { - const val = this.vars[VAR1(num)]; + const vars = this.vars; + const val = vars[VAR1(num)]; + const index = vars[VAR2(num)]; - if (IS_NUM(val) && org.mem.length < OConfig.orgMemSize) { - this.vars[VAR0(num)] = org.mem.push(val); + if (IS_NUM(val) && index < OConfig.orgMemSize) { + this.vars[VAR0(num)] = org.mem[index] = val; } else { this.vars[VAR0(num)] = 0; } diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 4478e9b..7ba1446 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -24,7 +24,7 @@ class OrganismDos extends Organism { } onRun() { - this.vm.run(this); + return this.vm.run(this); } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index f3669b8..ed28eee 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -37,17 +37,19 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, orgs :0, energy :0, penergy:0, eenergy :0, changes:0, fit :0, age :0, code :0, + lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age :0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killtour:0, killclone:0 }; this._stamp = 0; + this._ips = 0; + this._ipsTimes = 0; this._energy = 0; this._pickEnergy = 0; this._eatEnergy = 0; this._fitness = 0; this._changes = 0; this._codeSize = 0; - this._runLines = 0; + this._codeRuns = 0; this._age = 0; this._ageCount = 0; this._times = 0; @@ -56,6 +58,7 @@ class Status extends Configurable { this._firstCall = true; this._onLoopCb = this._onLoop.bind(this); + this._onIpsCb = this._onIps.bind(this); this._onEatEnergyCb = this._onEatEnergy.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); @@ -68,6 +71,7 @@ class Status extends Configurable { this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); Helper.override(manager, 'onLoop', this._onLoopCb); + manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); @@ -95,6 +99,7 @@ class Status extends Configurable { man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(manager, 'onLoop', this._onLoopCb); this._onKillOrgCb = null; @@ -107,6 +112,7 @@ class Status extends Configurable { this._onKillEatCb = null; this._onKillAgeCb = null; this._onKillEnergyCb = null; + this._onIpsCb = null; this._onLoopCb = null; this._status = null; this._statusCfg = null; @@ -150,7 +156,8 @@ class Status extends Configurable { this._onBeforeLoop(orgs); - status.lps = fix((this.parent.codeRuns - this._runLines) / ((stamp - this._stamp) / 1000), 0); + status.ips = fix(this._ips / this._ipsTimes, 2); + status.lps = fix((this.parent.codeRuns - this._codeRuns) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); status.penergy = fix(this._pickEnergy, 2); @@ -175,13 +182,20 @@ class Status extends Configurable { this._firstCall = false; } + _onIps(ips) { + this._ips += ips; + this._ipsTimes++; + } + _onAfterLoop(stamp) { this._times = 0; - this._runLines = this.parent.codeRuns; + this._codeRuns = this.parent.codeRuns; this._age = 0; this._ageCount = 0; this._eatEnergy = 0; this._pickEnergy = 0; + this._ips = 0; + this._ipsTimes = 0; this._stamp = stamp; _fill(this._kill, 0); } diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index 399e9c1..eab7373 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -9,6 +9,7 @@ */ const GoogleCharts = require('google-charts').GoogleCharts; const _get = require('lodash/get'); +const Config = require('./Config'); class Chart { constructor(title, cfg) { @@ -17,7 +18,7 @@ class Chart { hAxis : {textStyle: {fontSize: 10}}, vAxis : {textStyle: {fontSize: 10}, gridlines: {count: 10}}, legend : 'none', - chartArea: {left: 80, top: 30, bottom: 50, width: '100%', height: '100%'}, + chartArea: {left: 90, top: 30, bottom: 50, width: '100%', height: '100%'}, }; this._data = null; this._chart = null; @@ -39,6 +40,10 @@ class Chart { this._data.addRow(data); _get(this, '_cfg.active') && this._chart.draw(this._data, this._options); + if (this._data.getNumberOfRows() > Config.dataMaxSize) { + this._data.removeRows(0, Config.dataMaxSize * 0.1); + } + return true; } diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 11684c6..f085582 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -26,6 +26,7 @@ class Charts extends Status { this._data = new Array(2); this._charts = { lps : new Chart('LPS - Lines Per Second', Config.charts.lps), + ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), orgs : new Chart('Amount of organisms', Config.charts.orgs), energy : new Chart('Average organism energy', Config.charts.energy), penergy : new Chart('Average organism\'s picked energy (all)', Config.charts.penergy), @@ -124,8 +125,15 @@ class Charts extends Status { * @api */ _active(chart, a) { - if (typeof a === 'undefined') { - _each(this._charts, (c, k) => this._setProperty(k, 'active', typeof chart === 'undefined' ? true : chart)); + const noA = typeof a === 'undefined'; + const noChart = typeof chart === 'undefined'; + const bChart = typeof chart === 'boolean'; + + a = noA ? (bChart ? chart : true) : a; + chart = noChart ? null : (bChart ? null : chart); + + if (chart === null) { + _each(this._charts, (c, k) => this._setProperty(k, 'active', a)); } else { this._setProperty(chart, 'active', a); } diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index f1e7733..11a8f27 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -12,28 +12,34 @@ const Config = { * {Number} Delay in milliseconds between showing one status line */ period: 2000, + /** + * {Number} Maximum amount of chart rows, after which we will cut + * it on 10% + */ + dataMaxSize: 100000, /** * {Object} Available chart types */ charts: { - lps : {pos: 'downleft', active: false, transparent: 0.6}, - killout : {pos: 'topright', active: false, transparent: 0.6}, - orgs : {pos: '0-0|16', active: true, transparent: 0.6}, - energy : {pos: '0-1|16', active: true, transparent: 0.6}, - penergy : {pos: '0-2|16', active: true, transparent: 0.6}, - eenergy : {pos: '0-3|16', active: true, transparent: 0.6}, - fit : {pos: '1-0|16', active: true, transparent: 0.6}, - age : {pos: '1-1|16', active: true, transparent: 0.6}, - code : {pos: '1-2|16', active: true, transparent: 0.6}, - kill : {pos: '1-3|16', active: true, transparent: 0.6}, - killenergy: {pos: '2-0|16', active: true, transparent: 0.6}, - killage : {pos: '2-1|16', active: true, transparent: 0.6}, - killeat : {pos: '2-2|16', active: true, transparent: 0.6}, - killover : {pos: '2-3|16', active: true, transparent: 0.6}, - changes : {pos: '3-0|16', active: true, transparent: 0.6}, - killin : {pos: '3-1|16', active: true, transparent: 0.6}, - killtour : {pos: '3-2|16', active: true, transparent: 0.6}, - killclone : {pos: '3-3|16', active: true, transparent: 0.6} + lps : {pos: 'downleft', active: false, transparent: 0.8}, + ips : {pos: '3-3|16', active: true, transparent: 0.8}, + killout : {pos: 'topright', active: false, transparent: 0.8}, + orgs : {pos: '0-0|16', active: true, transparent: 0.8}, + energy : {pos: '0-1|16', active: true, transparent: 0.8}, + penergy : {pos: '0-2|16', active: true, transparent: 0.8}, + eenergy : {pos: '0-3|16', active: true, transparent: 0.8}, + fit : {pos: '1-0|16', active: true, transparent: 0.8}, + age : {pos: '1-1|16', active: true, transparent: 0.8}, + code : {pos: '1-2|16', active: true, transparent: 0.8}, + kill : {pos: '1-3|16', active: true, transparent: 0.8}, + killenergy: {pos: '2-0|16', active: true, transparent: 0.8}, + killage : {pos: '2-1|16', active: true, transparent: 0.8}, + killeat : {pos: '2-2|16', active: true, transparent: 0.8}, + killover : {pos: '2-3|16', active: true, transparent: 0.8}, + changes : {pos: '3-0|16', active: true, transparent: 0.8}, + killin : {pos: '3-1|16', active: true, transparent: 0.8}, + killtour : {pos: '3-2|16', active: true, transparent: 0.8}, + killclone : {pos: 'downright', active: false, transparent: 0.8} } }; diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 3e3353f..02609ed 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -42,8 +42,9 @@ class Console extends Status { const active = man.activeAround; const format = Console._format; - const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`; + const con = `${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '} `; const conns = `con:${con === ' ' ? 'no ' : con}`; + const sips = format(status.ips, 'ips', 12); const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); const senergy = format(status.energy, 'nrg', 17); @@ -56,7 +57,7 @@ class Console extends Status { const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/share/Events.js b/client/src/share/Events.js index cc456e5..cde602e 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -9,34 +9,35 @@ const EVENTS = { ITERATION : 0, LOOP : 1, - CODE_RUN : 2, - BACKUP : 3, - GRAB_ENERGY : 4, - UPDATE_ENERGY : 5, - KILL : 6, // general kill event - KILL_NO_ENERGY : 7, // killed if zero energy - KILL_AGE : 8, // killed if max age reached - KILL_EAT : 9, // killed, because other organism has eat this one - KILL_OVERFLOW : 10, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 11, // killed, because organism step outside the world - KILL_STEP_IN : 12, // killed, because of panishment for step in from near client - KILL_TOUR : 13, // killed in tournament - KILL_CLONE : 14, // killed, because of lack of energy after clone - MUTATIONS : 15, - CLONE : 16, - EAT : 17, - EAT_ORG : 18, - EAT_ENERGY : 19, - STEP : 20, - STEP_OUT : 21, - STEP_IN : 22, - BORN_ORGANISM : 23, - GET_ENERGY : 24, - DESTROY : 25, - RUN : 26, - STOP : 27, - RESET_CODE : 28, - CHECK_AT : 29 + IPS : 2, + CODE_RUN : 3, + BACKUP : 4, + GRAB_ENERGY : 5, + UPDATE_ENERGY : 6, + KILL : 7, // general kill event + KILL_NO_ENERGY : 8, // killed if zero energy + KILL_AGE : 9, // killed if max age reached + KILL_EAT : 10, // killed, because other organism has eat this one + KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 12, // killed, because organism step outside the world + KILL_STEP_IN : 13, // killed, because of panishment for step in from near client + KILL_TOUR : 14, // killed in tournament + KILL_CLONE : 15, // killed, because of lack of energy after clone + MUTATIONS : 16, + CLONE : 17, + EAT : 18, + EAT_ORG : 19, + EAT_ENERGY : 20, + STEP : 21, + STEP_OUT : 22, + STEP_IN : 23, + BORN_ORGANISM : 24, + GET_ENERGY : 25, + DESTROY : 26, + RUN : 27, + STOP : 28, + RESET_CODE : 29, + CHECK_AT : 30 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index e7d468a..86b5479 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -86,18 +86,19 @@ class VM extends Observer { * with line type callback. These callbacks interpret one line of code like: * condition, loop, function call etc... * @param {Organism} org Current organism + * @return {Number} Amount of run lines */ run(org) { - const code = this._code; - const lines = code.length; - const ops = this._ops; - const offs = this._offsets; - let len2 = lines === 0 ? 0 : OConfig.codeYieldPeriod || lines; - let len = len2; - let line = this._line; - let ret = false; + const code = this._code; + const lines = code.length; + const ops = this._ops; + const offs = this._offsets; + const period = OConfig.codeYieldPeriod; + let len = period; + let line = this._line; + let ret = false; - while (len-- > 0 && org.alive) { + while (len > 0 && org.alive) { line = ops[code[line] >>> VAR_BITS_OFFS](code[line], line, org, lines, ret); // // We reach the end of the script and have to run it from the beginning @@ -105,7 +106,7 @@ class VM extends Observer { if (line >= lines && org.alive) { line = 0; this._operators.offsets = this._offsets = []; - len2 = len; + len--; continue; } // @@ -116,9 +117,11 @@ class VM extends Observer { offs.pop(); line = offs.pop(); } + len--; } - this._line = line; + + return period - len; } destroy() { @@ -235,13 +238,17 @@ class VM extends Observer { } /** - * Generates random code of organism with specified size - * @param {Number} size Final code size + * Generates random code and inserts it starting from 'pos'. The + * length of generated code is 'size'. Final code length shouldn't + * be greater then original size. + * @param {Number} pos Insert position + * @param {Number} size generated code size */ - generate(size) { - const code = this._code = new Array(size); + generate(pos, size) { + const orgCode = this._code; - for (let i = 0; i < size; i++) {code[i] = Num.get()} + size = pos + size; + while (pos < size) {orgCode[pos++] = Num.get()} this._reset(); } From cfe3779c973b9959b3969e996f4a0ef2e12e3442 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 19 Jan 2018 12:12:31 +0200 Subject: [PATCH 139/291] changed default config value for stepping out of the world --- client/src/manager/plugins/organisms/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4e940d4..03be45a 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -131,7 +131,7 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.3, + orgStepEnergySpendPercent: 0.0, /** * {Number} Percent from orgMaxOrgs config, which is used for crossing borders * between clients/Managers. Entire amount of organisms within one client = From c54a8c245506cff2ab25962a0f0d01332c4c006a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 19 Jan 2018 23:55:30 +0200 Subject: [PATCH 140/291] added orgMutationPerOrg config removed orgGarbagePeriod config fixed issue with minus keys in memory fixed 0 fitness in Status plugin --- .../src/manager/plugins/organisms/Config.js | 36 ++++++++----------- .../src/manager/plugins/organisms/Mutator.js | 1 + .../src/manager/plugins/organisms/Organism.js | 6 ++-- .../plugins/organisms/dos/Operators.js | 4 +-- client/src/manager/plugins/status/Status.js | 2 +- 5 files changed, 22 insertions(+), 27 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 03be45a..abb94f5 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -45,7 +45,12 @@ const Config = { * copy - Probability of copying of code lines inside it's own code * ] */ - orgMutationProbs: [1,1,100,1,1,1,1,1,1,10,1], + orgMutationProbs: [1,1,90,1,1,1,1,1,1,10,1], + /** + * {Boolean} If turned on, then organism will be responsible for changing + * mutations probabilities. Otherwise these probabilities will be constant + */ + orgMutationPerOrg: false, /** * {Number} Percent of energy, which will be given to the child. Set to 0.0 * to share the same amount of energy with child (energy duplication) @@ -71,12 +76,12 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 5000, + orgRainMutationPeriod: 0, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.02, + orgRainMutationPercent: 0.01, /** * {Boolean} Turn this flag on to give organism a possibility to choose his * own mutations period and percent. false - mean, that these values will be @@ -94,35 +99,22 @@ const Config = { * is how natural selection is implemented in our system. Set this parameter * to 0 and tournament mechanism will be turned off */ - orgTournamentPeriod: 50, + orgTournamentPeriod: 500, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 2000, + orgRandomOrgPeriod: 5000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. */ - orgEnergySpendPeriod: 10, + orgEnergySpendPeriod: 30, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 50000, - /** - * {Number} This value means the period between organism codeSizes, which - * affects energy grabbing by the system. For example: we have two - * organisms: org1.energy = 10, org2.energy = 10, org1.codeSize = 6, - * org2.codeSize = 9, OConfig.orgGarbagePeriod = 5. It means that - * during energy grabbing by the system org1 and org2 will spend the - * same amount of energy - 1 unit. This is because the period goes - * from 1..5, 6..10,... and both organisms are in the same period. In - * simple words, if your size is between 0-20, then 1 unit of energy will - * be grabbed from you. If your size is between 21-40, then 2 units of - * energy will be grabbed from you and so on... - */ - orgGarbagePeriod: 7, + orgAlivePeriod: 40000, /** * {Number} Size of organism stack (internal memory) */ @@ -146,11 +138,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 300, + orgMaxOrgs: 50, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 300, + orgStartAmount: 50, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index a5d2b65..ac84664 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -70,6 +70,7 @@ class Mutator { } static _onProbs(org) { + if (!OConfig.orgMutationPerOrg) {return} org.mutationProbs[Helper.rand(org.mutationProbs.length)] = Helper.rand(OConfig.ORG_MUTATION_PROBS_MAX_VAL) || 1; org.changes++; } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 85bc0d3..304389c 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -191,9 +191,11 @@ class Organism extends Observer { return !noEnergy; } + // TODO: describe fitness in details fitness() { //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); - return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); + //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); + return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); } destroy() { @@ -273,7 +275,7 @@ class Organism extends Observer { return true; } if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - let grabSize = Math.round(this.vm.size / OConfig.orgGarbagePeriod); + let grabSize = this.vm.size; if (grabSize < 1) {grabSize = 1} (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 7513e27..1fa2dc0 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -199,7 +199,7 @@ class OperatorsDos extends Operators { onFromMem(num, line, org) { const index = this.vars[VAR1(num)]; - this.vars[VAR0(num)] = index >= org.mem.length ? 0 : org.mem[index]; + this.vars[VAR0(num)] = index < 0 || index >= org.mem.length ? 0 : org.mem[index]; return ++line; } onToMem(num, line, org) { @@ -207,7 +207,7 @@ class OperatorsDos extends Operators { const val = vars[VAR1(num)]; const index = vars[VAR2(num)]; - if (IS_NUM(val) && index < OConfig.orgMemSize) { + if (IS_NUM(val) && index >= 0 && index < OConfig.orgMemSize) { this.vars[VAR0(num)] = org.mem[index] = val; } else { this.vars[VAR0(num)] = 0; diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index ed28eee..cabbd08 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -163,7 +163,7 @@ class Status extends Configurable { status.penergy = fix(this._pickEnergy, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); status.changes = +(this._changes).toFixed(1); - status.fit = fix(this._fitness / 10000000, 2); + status.fit = fix(this._fitness / 100, 2); status.age = fix(this._age / (this._ageCount || 1), 2); status.code = +(this._codeSize / orgAmount).toFixed(2); From 0f4837f62974574a2a63d1816845b8b53cbed80f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 20 Jan 2018 13:23:29 +0200 Subject: [PATCH 141/291] simplified fromMem() and toMem() operators config orgMemSize was changed to orgMemBits memory should contain zero values et the beginning started new experiment with small amount of energy, but very energetic in one point --- .../src/manager/plugins/organisms/Config.js | 24 ++++++++++--------- .../src/manager/plugins/organisms/Organism.js | 5 +++- .../plugins/organisms/dos/Code2String.js | 6 +++-- .../plugins/organisms/dos/Operators.js | 20 ++++------------ client/src/share/Config.js | 6 ++--- 5 files changed, 29 insertions(+), 32 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index abb94f5..0eac938 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -50,7 +50,7 @@ const Config = { * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant */ - orgMutationPerOrg: false, + orgMutationPerOrg: true, /** * {Number} Percent of energy, which will be given to the child. Set to 0.0 * to share the same amount of energy with child (energy duplication) @@ -70,13 +70,13 @@ const Config = { * own clone period and percent. false - mean, that these values will be constant * for all organisms */ - orgClonePerOrg: false, + orgClonePerOrg: true, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 0, + orgRainMutationPeriod: 1000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -87,12 +87,12 @@ const Config = { * own mutations period and percent. false - mean, that these values will be * constant for all organisms */ - orgRainPerOrg: false, + orgRainPerOrg: true, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 0, + orgCrossoverPeriod: 1000, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This @@ -116,9 +116,11 @@ const Config = { */ orgAlivePeriod: 40000, /** - * {Number} Size of organism stack (internal memory) + * {Number} Size of organism stack (internal memory) in bits. Real amount of + * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, + * then memory=2^3 === 8 numbers */ - orgMemSize: 128, + orgMemBits: 8, /** * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. @@ -138,11 +140,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 50, + orgMaxOrgs: 200, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 50, + orgStartAmount: 200, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -159,13 +161,13 @@ const Config = { * default value, while organism is delivering. So, if the value is * 1000, then ragne will be: -500..500 */ - codeVarInitRange: 1000, + codeVarInitRange: 100, /** * {Number} This value is amount of code lines, which will be run for one * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 10, + codeYieldPeriod: 5, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 304389c..af15ebf 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -5,6 +5,7 @@ * TODO: - * @author flatline */ +const _fill = require('lodash/fill'); const Observer = require('./../../../../../common/src/Observer'); const Helper = require('./../../../../../common/src/Helper'); const OConfig = require('./../../../manager/plugins/organisms/Config'); @@ -224,7 +225,9 @@ class Organism extends Observer { this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; - this._mem = new Array(OConfig.orgMemSize); + this._mem = new Array(Math.pow(2, OConfig.orgMemBits)); + + _fill(this._mem, 0); } _clone(parent) { diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 2a9624d..9bbce53 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -14,11 +14,13 @@ const VAR0 = Num.getVar; const VAR1 = (n) => Num.getVar(n, 1); const VAR2 = (n) => Num.getVar(n, 2); const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; +const BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; const BLOCK_MAX_LEN = OConfig.codeBitsPerBlock; const BITS_FOR_NUMBER = 16; const FOUR_BITS = 4; const CONDITION_BITS = 2; const HALF_OF_VAR = Num.MAX_VAR / 2; +const BITS = Num.getBits; class Code2String { constructor(manager) { @@ -215,11 +217,11 @@ class Code2String { } _onFromMem(num) { - return `v${VAR0(num)}=fromMem(v${VAR1(num)})`; + return `v${VAR0(num)}=fromMem(${BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; } _onToMem(num) { - return `v${VAR0(num)}=toMem(v${VAR1(num)},v${VAR2(num)})`; + return `toMem(v${VAR0(num)},${BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; } _onMyX(num) { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 1fa2dc0..4178291 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -20,8 +20,8 @@ const VAR0 = Num.getVar0; const VAR1 = Num.getVar1; const VAR2 = Num.getVar2; const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; +const BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; const FOUR_BITS = 4; -const BLOCK_MAX_LEN = OConfig.codeBitsPerBlock; const BITS_FOR_NUMBER = 16; const IS_NUM = Helper.isNumeric; const HALF_OF_VAR = Num.MAX_VAR / 2; @@ -106,7 +106,7 @@ class OperatorsDos extends Operators { //} onCondition(num, line, org, lines) { - const val3 = BITS(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const val3 = BITS(num, BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); const offs = this._getOffs(line, lines, val3); const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); @@ -123,7 +123,7 @@ class OperatorsDos extends Operators { onLoop(num, line, org, lines, afterIteration = false) { const vars = this.vars; const var0 = VAR0(num); - const val3 = BITS(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const val3 = BITS(num, BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); const offs = this._getOffs(line, lines, val3); // // If last iteration has done and we've returned to the line, @@ -198,21 +198,11 @@ class OperatorsDos extends Operators { onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} onFromMem(num, line, org) { - const index = this.vars[VAR1(num)]; - this.vars[VAR0(num)] = index < 0 || index >= org.mem.length ? 0 : org.mem[index]; + this.vars[VAR0(num)] = org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; return ++line; } onToMem(num, line, org) { - const vars = this.vars; - const val = vars[VAR1(num)]; - const index = vars[VAR2(num)]; - - if (IS_NUM(val) && index >= 0 && index < OConfig.orgMemSize) { - this.vars[VAR0(num)] = org.mem[index] = val; - } else { - this.vars[VAR0(num)] = 0; - } - + org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[VAR0(num)]; return ++line; } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 577c4c8..935db09 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -63,12 +63,12 @@ ClientConfig.init({ * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... */ - worldEnergyDots: 10000, + worldEnergyDots: 100, /** * {Number} Amount of energy in every block. See worldEnergyDots * config for details. */ - worldEnergyInDot: 0x00FF00, + worldEnergyInDot: 0xFFFF00, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less @@ -76,7 +76,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.4, + worldEnergyCheckPercent: 0.0003, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if From 053f31b93fa5f9bfebc5a7d0f51120628709339c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 20 Jan 2018 13:49:53 +0200 Subject: [PATCH 142/291] changed base fitness function rule. from now, fitness depends only from energy --- client/src/manager/plugins/organisms/Config.js | 6 +++--- client/src/manager/plugins/organisms/Organism.js | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 0eac938..5e51d44 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -92,7 +92,7 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 1000, + orgCrossoverPeriod: 4000, /** * {Number} Period of tournament between organisms. If amount of organisms * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This @@ -104,7 +104,7 @@ const Config = { * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 5000, + orgRandomOrgPeriod: 7000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -159,7 +159,7 @@ const Config = { /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is - * 1000, then ragne will be: -500..500 + * 1000, then range will be: -500..500 */ codeVarInitRange: 100, /** diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index af15ebf..7e7a614 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -196,7 +196,8 @@ class Organism extends Observer { fitness() { //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); - return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); + //return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); + return this._energy; } destroy() { From a3730bf18a660a1e04a7c38515bfd60083ce6a71 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 20 Jan 2018 17:37:14 +0200 Subject: [PATCH 143/291] fixed #106. added ips and status info at left top corner fixed #65. removed extra configs fixed black color issue #18 added smooth organisms color change fixed an issue of wrong calculation of penergy --- client/src/manager/plugins/client/Config.js | 9 ---- .../src/manager/plugins/organisms/Config.js | 15 ++----- .../src/manager/plugins/organisms/Organism.js | 29 +++++++++++-- client/src/manager/plugins/status/Status.js | 4 +- .../manager/plugins/status/charts/Chart.js | 2 +- .../manager/plugins/status/charts/Charts.js | 42 +++++++++++++++---- 6 files changed, 66 insertions(+), 35 deletions(-) delete mode 100644 client/src/manager/plugins/client/Config.js diff --git a/client/src/manager/plugins/client/Config.js b/client/src/manager/plugins/client/Config.js deleted file mode 100644 index 30fd847..0000000 --- a/client/src/manager/plugins/client/Config.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Configuration of Client plugin - * - * @author flatline - */ -const Config = { -}; - -module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5e51d44..b4d830b 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -8,15 +8,6 @@ const Config = { * {Number} Maximum amount of iterations for clone period */ ORG_MAX_CLONE_PERIOD: 10000, - /** - * {Number} Index of first color of organism. After maximum color this - * color will be applied - */ - ORG_FIRST_COLOR: 1, - /** - * {Number} Maximum color index of organism - */ - ORG_MAX_COLOR: 0xFFFFFF, /** * {Number} Max value, which we may use in orgMutationProbs array. We may use * range: [0...ORG_MUTATION_PROBS_MAX_VAL] including these values @@ -152,10 +143,10 @@ const Config = { */ orgStartEnergy: 100000, /** - * {Number} Begin color of "empty" organism (organism without code). Color - * should be set in HEX-RGB mode. Example: 0xRRGGBB + * {Number} Begin color of "empty". It's just an index of color. Starts from + * 0 and till Number.MAX_VALUE */ - orgStartColor: 0xFF0000, + orgStartColor: 18, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 7e7a614..da8f01f 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -11,6 +11,9 @@ const Helper = require('./../../../../../common/src/Helper'); const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; const VM = require('./../../../vm/VM'); +const Num = require('./../../../vm/Num'); + +const MAX_BITS = Num.MAX_BITS; const GRAB_ENERGY = 0; const DESTROY = 1; @@ -30,6 +33,21 @@ const ORG_EVENTS = { const IS_NUM = Helper.isNumeric; class Organism extends Observer { + /** + * Returns color by index. Index may be increased without limit + * @param {Number} index Color index. Starts from 0 till Number.MAX_VALUE + * @returns {Number} RGB value + */ + static _getColor(index) { + const frequency = 0.1; + + const r = Math.sin(frequency * index ) * 127 + 128; + const g = Math.sin(frequency * index + 2) * 127 + 128; + const b = Math.sin(frequency * index + 4) * 127 + 128; + + return r << 16 | g << 8 | b; + } + /** * Is called before every run. Should return true, if everything * is okay and we don't need to interrupt running. If true, then @@ -91,6 +109,7 @@ class Organism extends Observer { get energy() {return this._energy} get startEnergy() {return this._startEnergy} get color() {return this._color} + get colorIndex() {return this._colorIndex} get mem() {return this._mem} get posId() {return Helper.posId(this._x, this._y)} @@ -143,6 +162,7 @@ class Organism extends Observer { energy : this._energy, startEnergy : this._startEnergy, color : this._color, + colorIndex : this._colorIndex, mutationProbs : this._mutationProbs, cloneMutationPercent: this._cloneMutationPercent, cloneEnergyPercent : this._cloneEnergyPercent, @@ -175,6 +195,7 @@ class Organism extends Observer { this._energy = json.energy; this._startEnergy = json.startEnergy; this._color = json.color; + this._colorIndex = json.colorIndex; this._mutationProbs = json.mutationProbs; this._cloneMutationPercent = json.cloneMutationPercent; this._cloneEnergyPercent = json.cloneEnergyPercent; @@ -219,7 +240,8 @@ class Organism extends Observer { this.vm = new VM(this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; - this._color = OConfig.orgStartColor; + this._colorIndex = OConfig.orgStartColor; + this._color = Organism._getColor(0); this._mutationProbs = OConfig.orgMutationProbs.slice(); this._cloneMutationPercent = OConfig.orgCloneMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; @@ -236,6 +258,7 @@ class Organism extends Observer { this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; + this._colorIndex = parent.colorIndex; this._mutationProbs = parent.mutationProbs.slice(); this._cloneMutationPercent = parent.cloneMutationPercent; this._cloneEnergyPercent = parent.cloneEnergyPercent; @@ -246,9 +269,7 @@ class Organism extends Observer { } _updateColor(changes) { - if ((this._color += changes) > OConfig.ORG_MAX_COLOR) { - this._color = OConfig.ORG_FIRST_COLOR; - } + this._color = Organism._getColor(this._colorIndex = Math.round(changes / MAX_BITS)); } /** diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index cabbd08..a312ddf 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -122,6 +122,7 @@ class Status extends Configurable { const size = orgs.size || 1; let energy = 0; let startEnergy = 0; + let iterations = 0; let fitness = 0; let changes = 0; let codeSize = 0; @@ -131,13 +132,14 @@ class Status extends Configurable { while(item && (org = item.val)) { energy += org.energy; startEnergy += org.startEnergy; + iterations += org.iterations; changes += org.changes; fitness += org.fitness(); codeSize += org.vm.size; item = item.next; } - this._pickEnergy = (energy - startEnergy) / size; + this._pickEnergy = ((energy - startEnergy) / iterations) / size; this._energy = energy / size; this._changes = changes / size; this._fitness = fitness / size; diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index eab7373..cca2120 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -18,7 +18,7 @@ class Chart { hAxis : {textStyle: {fontSize: 10}}, vAxis : {textStyle: {fontSize: 10}, gridlines: {count: 10}}, legend : 'none', - chartArea: {left: 90, top: 30, bottom: 50, width: '100%', height: '100%'}, + chartArea: {left: 90, top: 30, bottom: 50, right: 3, width: '100%', height: '100%'}, }; this._data = null; this._chart = null; diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index f085582..7e805ae 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -24,6 +24,7 @@ class Charts extends Status { const periodSec = Config.period / 1000; this._data = new Array(2); + this._header = this._createHeader(); this._charts = { lps : new Chart('LPS - Lines Per Second', Config.charts.lps), ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), @@ -58,17 +59,14 @@ class Charts extends Status { /** * Is called every time, when new status data is available * @param {Object} status Status data - * @param {Number} orgs Amount of organisms * @override */ - onStatus(status, orgs) { - //console.log(`%c${conns}${slps}${sorgs}%c${siq}${penergy}${schanges}${sfit}${sage}${scode}`, GREEN, RED); - // TODO: this code should be moved to separate plugin - // TODO: add energy, orgs and code: e:xxx, o:xxx, c:xxx - //const active = man.activeAround; - //man.canvas && man.canvas.text(5, 20, `${man.clientId && man.clientId || ''} ${active[0] ? '^' : ' '}${active[1] ? '>' : ' '}${active[2] ? 'v' : ' '}${active[3] ? '<' : ' '}`); - + onStatus(status) { + this._updateCharts(status); + this._updateHeader(status); + } + _updateCharts(status) { const data = this._data; const charts = this._charts; data[0] = this._to12h(new Date); @@ -79,6 +77,19 @@ class Charts extends Status { }); } + _updateHeader(status) { + const man = this.parent; + const active = man.activeAround; + if (!man.canvas) {return} + const conns = `${active[0] ? '^' : ''}${active[1] ? '>' : ''}${active[2] ? 'v' : ''}${active[3] ? '<' : ''}`; + const ips = `ips:${status.ips}`; + const pnrg = `pnrg:${status.penergy}`; + const code = `cod:${status.code}`; + let header = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; + + this._header.textContent = header; + } + _to12h(time) { let hours = time.getHours(); let minutes = time.getMinutes(); @@ -89,6 +100,21 @@ class Charts extends Status { return hours + ':' + minutes; } + _createHeader() { + const el = this._el = document.createElement("DIV"); + + el.style.position = 'absolute'; + el.style.top = '5px'; + el.style.left = '5px'; + el.style.color = '#fff'; + el.style.fontSize = '18px'; + el.style.fontFamily = 'Consolas'; + + document.body.appendChild(el); + + return el; + } + /** * Sets specified chart transparent coefficient. May be called * with one Number parameter to set it for all charts. From 82ed46efa5905b68cf6f8b5454055df5e14b735c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 21 Jan 2018 11:03:51 +0200 Subject: [PATCH 144/291] removed separated tournament logic. it's moved to clone logic --- .../src/manager/plugins/organisms/Config.js | 16 +------ .../src/manager/plugins/organisms/Mutator.js | 13 ++---- .../src/manager/plugins/organisms/Organism.js | 21 ++------- .../manager/plugins/organisms/Organisms.js | 43 ++++++------------- client/src/manager/plugins/status/Status.js | 9 +--- .../manager/plugins/status/charts/Charts.js | 1 - .../manager/plugins/status/charts/Config.js | 5 +-- client/src/share/Config.js | 6 +-- client/src/share/Events.js | 32 +++++++------- 9 files changed, 44 insertions(+), 102 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index b4d830b..2df1fbf 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -4,10 +4,6 @@ * @author flatline */ const Config = { - /** - * {Number} Maximum amount of iterations for clone period - */ - ORG_MAX_CLONE_PERIOD: 10000, /** * {Number} Max value, which we may use in orgMutationProbs array. We may use * range: [0...ORG_MUTATION_PROBS_MAX_VAL] including these values @@ -31,12 +27,11 @@ const Config = { * amount - Probability of amount of mutations per period * probs - Probability of change one of probability coefficient in this array * clone-percent - Probability of change clone energy percent value - * clone-period - Probability of change clone period value * add - Probability of adding new line to the code * copy - Probability of copying of code lines inside it's own code * ] */ - orgMutationProbs: [1,1,90,1,1,1,1,1,1,10,1], + orgMutationProbs: [1,1,90,1,1,1,1,1,10,1], /** * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant @@ -84,13 +79,6 @@ const Config = { * to random organisms. May be set to 0 to turn crossover off */ orgCrossoverPeriod: 4000, - /** - * {Number} Period of tournament between organisms. If amount of organisms - * is >= of maximum (orgMaxOrgs), then looser organism will be killed. This - * is how natural selection is implemented in our system. Set this parameter - * to 0 and tournament mechanism will be turned off - */ - orgTournamentPeriod: 500, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature @@ -100,7 +88,7 @@ const Config = { * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. */ - orgEnergySpendPeriod: 30, + orgEnergySpendPeriod: 10, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index ac84664..43758a4 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -20,7 +20,7 @@ const MAX_VAR = Num.MAX_VAR; const MAX_BITS = Num.MAX_BITS; const BITS_PER_VAR = Num.BITS_PER_VAR; -const ADD_MUTAION_INDEX = 9; +const ADD_MUTAION_INDEX = 8; class Mutator { static _onChange(org) { @@ -75,7 +75,7 @@ class Mutator { org.changes++; } - static _onClone(org) { + static _onCloneMutationPercent(org) { if (!OConfig.orgClonePerOrg) {return} org.cloneMutationPercent = Math.random(); org.changes++; @@ -87,12 +87,6 @@ class Mutator { org.changes++; } - static _onClonePeriod(org) { - if (!OConfig.orgClonePerOrg) {return} - org.clonePeriod = Helper.rand(OConfig.ORG_MAX_CLONE_PERIOD); - org.changes++; - } - static _onAdd(org) { org.vm.insertLine(); org.changes += MAX_BITS; @@ -112,9 +106,8 @@ class Mutator { Mutator._onMutationPeriod, Mutator._onMutationPercent, Mutator._onProbs, - Mutator._onClone, + Mutator._onCloneMutationPercent, Mutator._onCloneEnergyPercent, - Mutator._onClonePeriod, Mutator._onAdd, Mutator._onCopy ]; diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index da8f01f..0c6fffb 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -105,7 +105,6 @@ class Organism extends Observer { get mutationPercent() {return this._mutationPercent} get cloneMutationPercent() {return this._cloneMutationPercent} get cloneEnergyPercent() {return this._cloneEnergyPercent} - get clonePeriod() {return this._clonePeriod} get energy() {return this._energy} get startEnergy() {return this._startEnergy} get color() {return this._color} @@ -117,7 +116,6 @@ class Organism extends Observer { set y(newY) {this._y = newY} set cloneMutationPercent(m) {this._cloneMutationPercent = m} set cloneEnergyPercent(p) {this._cloneEnergyPercent = p} - set clonePeriod(p) {this._clonePeriod = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} set energy(e) {this._energy = e} @@ -136,7 +134,6 @@ class Organism extends Observer { this.fire(ITERATION, lines, this); if (this._alive) { - this._alive && this._updateClone(); this._alive && this._updateAge(); this._alive && this._updateEnergy(); } @@ -166,7 +163,6 @@ class Organism extends Observer { mutationProbs : this._mutationProbs, cloneMutationPercent: this._cloneMutationPercent, cloneEnergyPercent : this._cloneEnergyPercent, - clonePeriod : this._clonePeriod, mutationPeriod : this._mutationPeriod, mutationPercent : this._mutationPercent, mem : this.mem.slice() @@ -199,7 +195,6 @@ class Organism extends Observer { this._mutationProbs = json.mutationProbs; this._cloneMutationPercent = json.cloneMutationPercent; this._cloneEnergyPercent = json.cloneEnergyPercent; - this._clonePeriod = json.clonePeriod; this._mutationPeriod = json.mutationPeriod; this._mutationPercent = json.mutationPercent; this._mem = json.mem.slice(); @@ -215,6 +210,7 @@ class Organism extends Observer { // TODO: describe fitness in details fitness() { + // TODO: check these variants //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); //return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); @@ -245,7 +241,6 @@ class Organism extends Observer { this._mutationProbs = OConfig.orgMutationProbs.slice(); this._cloneMutationPercent = OConfig.orgCloneMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; - this._clonePeriod = OConfig.orgClonePeriod; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; this._mem = new Array(Math.pow(2, OConfig.orgMemBits)); @@ -262,7 +257,6 @@ class Organism extends Observer { this._mutationProbs = parent.mutationProbs.slice(); this._cloneMutationPercent = parent.cloneMutationPercent; this._cloneEnergyPercent = parent.cloneEnergyPercent; - this._clonePeriod = parent.clonePeriod; this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; this._mem = parent.mem.slice(); @@ -300,22 +294,13 @@ class Organism extends Observer { return true; } if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - let grabSize = this.vm.size; + //let grabSize = this.vm.size; + let grabSize = 1; if (grabSize < 1) {grabSize = 1} (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } - - /** - * Current organism wants to clone himself - * @return {Boolean} - */ - _updateClone() { - if (this._iterations % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0) {return true} - this.fire(CLONE, this); - return true; - } } module.exports = {EVENTS: ORG_EVENTS, Organism}; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index ff62180..564a3df 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -114,7 +114,6 @@ class Organisms extends Configurable { addOrgHandlers(org) { org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); - org.on(ORG_EVENTS.CLONE, this._onCloneOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); org.on(ORG_EVENTS.ITERATION, this._onIterationOrg.bind(this)); @@ -185,7 +184,7 @@ class Organisms extends Configurable { item = item.next; } - this._updateAmount(counter); + this._updateClone(counter); this._updateRandomOrgs(counter); this._updateCrossover(counter); } @@ -259,10 +258,6 @@ class Organisms extends Configurable { //Console.info(org.id, ' die'); } - _onCloneOrg(org) { - this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); - } - _onKillNoEnergyOrg(org) {this._parent.fire(EVENTS.KILL_NO_ENERGY, org)} _onKillAgeOrg(org) {this._parent.fire(EVENTS.KILL_AGE, org)} _onIterationOrg(lines, org) { @@ -270,29 +265,19 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - /** - * Does tournament between two random organisms and kill looser, if amount of - * organisms is greater or equal to maximum (OConfig.orgMaxOrgs). In general - * this function is a natural selection in our system. - * @param {Number} counter Current value of global iterations counter - * @returns {Boolean} true - amount is less then maximum, false - otherwise - */ - _updateAmount(counter) { - let orgAmount = this.organisms.size; - if (counter % OConfig.orgTournamentPeriod !== 0 || orgAmount < 1 || OConfig.orgTournamentPeriod === 0) {return true} - let org1 = this.randOrg(); - let org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} - - if (this._tournament(org1, org2) === org2) { - this.parent.fire(EVENTS.KILL_TOUR, org1); - org1.destroy(); - } else { - this.parent.fire(EVENTS.KILL_TOUR, org2); - org2.destroy(); - } + _updateClone(counter) { + const orgAmount = this.organisms.size; + if (counter % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0 || orgAmount < 1) {return true} + let org1 = this.randOrg(); + if (org1.alive && orgAmount < OConfig.orgMaxOrgs) {this._clone(org1);return} + let org2 = this.randOrg(); + if (!org1.alive || !org2.alive || org1 === org2) {return false} - return true; + if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + + this._clone(org1); + this.parent.fire(EVENTS.KILL_OVERFLOW, org2); + org2.destroy(); } _updateRandomOrgs(counter) { @@ -318,7 +303,7 @@ class Organisms extends Configurable { if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); - if ((orgAmount + 1) > OConfig.orgMaxOrgs) { + if (orgAmount + 1 >= OConfig.orgMaxOrgs) { this.parent.fire(EVENTS.KILL_OVERFLOW, org1); org1.destroy(); } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index a312ddf..8e218af 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -37,8 +37,8 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age :0, code:0, - kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killtour:0, killclone:0 + lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age:0, code:0, + kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killclone:0 }; this._stamp = 0; this._ips = 0; @@ -67,7 +67,6 @@ class Status extends Configurable { this._onKillOverCb = this._onKillHandlerOrg.bind(this, 4); this._onKillOutCb = this._onKillHandlerOrg.bind(this, 5); this._onKillInCb = this._onKillHandlerOrg.bind(this, 6); - this._onKillTourCb = this._onKillHandlerOrg.bind(this, 7); this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); Helper.override(manager, 'onLoop', this._onLoopCb); @@ -80,7 +79,6 @@ class Status extends Configurable { manager.on(EVENTS.KILL_OVERFLOW, this._onKillOverCb); manager.on(EVENTS.KILL_STEP_OUT, this._onKillOutCb); manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); - manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); _fill(this._kill, 0); @@ -90,7 +88,6 @@ class Status extends Configurable { const man = this.parent; man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); - man.off(EVENTS.KILL_TOUR, this._onKillTourCb); man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); man.off(EVENTS.KILL_STEP_OUT, this._onKillOutCb); man.off(EVENTS.KILL_OVERFLOW, this._onKillOverCb); @@ -105,7 +102,6 @@ class Status extends Configurable { this._onKillOrgCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; - this._onKillTourCb = null; this._onKillInCb = null; this._onKillOutCb = null; this._onKillOverCb = null; @@ -176,7 +172,6 @@ class Status extends Configurable { status.killover = fix(this._kill[4], 2); status.killout = fix(this._kill[5], 2); status.killin = fix(this._kill[6], 2); - status.killtour = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); !this._firstCall && this.onStatus(status, orgs.size); diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 7e805ae..b4f46d1 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -43,7 +43,6 @@ class Charts extends Status { killover : new Chart(`Amount of organisms killed after overflow per ${periodSec} sec`, Config.charts.killover), killout : new Chart(`Amount of organisms killed after step out per ${periodSec} sec`, Config.charts.killout), killin : new Chart(`Amount of organisms killed after step in per ${periodSec} sec`, Config.charts.killin), - killtour : new Chart(`Amount of organisms killed in tournament per ${periodSec} sec`, Config.charts.killtour), killclone : new Chart(`Amount of organisms killed during clone per ${periodSec} sec`, Config.charts.killclone) }; } diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 11a8f27..2e7501d 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -22,7 +22,6 @@ const Config = { */ charts: { lps : {pos: 'downleft', active: false, transparent: 0.8}, - ips : {pos: '3-3|16', active: true, transparent: 0.8}, killout : {pos: 'topright', active: false, transparent: 0.8}, orgs : {pos: '0-0|16', active: true, transparent: 0.8}, energy : {pos: '0-1|16', active: true, transparent: 0.8}, @@ -38,8 +37,8 @@ const Config = { killover : {pos: '2-3|16', active: true, transparent: 0.8}, changes : {pos: '3-0|16', active: true, transparent: 0.8}, killin : {pos: '3-1|16', active: true, transparent: 0.8}, - killtour : {pos: '3-2|16', active: true, transparent: 0.8}, - killclone : {pos: 'downright', active: false, transparent: 0.8} + killclone : {pos: '3-2|16', active: true, transparent: 0.8}, + ips : {pos: '3-3|16', active: true, transparent: 0.8} } }; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 935db09..51b5af0 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -63,12 +63,12 @@ ClientConfig.init({ * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... */ - worldEnergyDots: 100, + worldEnergyDots: 1000, /** * {Number} Amount of energy in every block. See worldEnergyDots * config for details. */ - worldEnergyInDot: 0xFFFF00, + worldEnergyInDot: 0xAAFF00, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less @@ -76,7 +76,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.0003, + worldEnergyCheckPercent: 0.2, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if diff --git a/client/src/share/Events.js b/client/src/share/Events.js index cde602e..e58ccc8 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -21,23 +21,21 @@ const EVENTS = { KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism KILL_STEP_OUT : 12, // killed, because organism step outside the world KILL_STEP_IN : 13, // killed, because of panishment for step in from near client - KILL_TOUR : 14, // killed in tournament - KILL_CLONE : 15, // killed, because of lack of energy after clone - MUTATIONS : 16, - CLONE : 17, - EAT : 18, - EAT_ORG : 19, - EAT_ENERGY : 20, - STEP : 21, - STEP_OUT : 22, - STEP_IN : 23, - BORN_ORGANISM : 24, - GET_ENERGY : 25, - DESTROY : 26, - RUN : 27, - STOP : 28, - RESET_CODE : 29, - CHECK_AT : 30 + KILL_CLONE : 14, // killed, because of lack of energy after clone + MUTATIONS : 15, + EAT : 16, + EAT_ORG : 17, + EAT_ENERGY : 18, + STEP : 19, + STEP_OUT : 20, + STEP_IN : 21, + BORN_ORGANISM : 22, + GET_ENERGY : 23, + DESTROY : 24, + RUN : 25, + STOP : 26, + RESET_CODE : 27, + CHECK_AT : 28 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; From 9c74e6d4ec2703dfd09a0a4ac555efab59fcba1d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 21 Jan 2018 15:33:37 +0200 Subject: [PATCH 145/291] new version of default config fixed issue with color of organisms fixed issue with negative changes amount --- .../src/manager/plugins/organisms/Config.js | 14 ++++----- .../src/manager/plugins/organisms/Organism.js | 5 ++-- .../manager/plugins/organisms/Organisms.js | 2 +- .../manager/plugins/status/charts/Chart.js | 29 +++++++++--------- .../manager/plugins/status/charts/Charts.js | 30 ++++++++----------- client/src/view/Canvas.js | 24 ++++++++------- common/src/Helper.js | 24 ++++++++++++--- 7 files changed, 73 insertions(+), 55 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 2df1fbf..29b6e3b 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -36,7 +36,7 @@ const Config = { * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant */ - orgMutationPerOrg: true, + orgMutationPerOrg: false, /** * {Number} Percent of energy, which will be given to the child. Set to 0.0 * to share the same amount of energy with child (energy duplication) @@ -50,7 +50,7 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 100, + orgClonePeriod: 400, /** * {Boolean} Turn this flag on to give organism a possibility to choose his * own clone period and percent. false - mean, that these values will be constant @@ -62,7 +62,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 1000, + orgRainMutationPeriod: 20000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -73,7 +73,7 @@ const Config = { * own mutations period and percent. false - mean, that these values will be * constant for all organisms */ - orgRainPerOrg: true, + orgRainPerOrg: false, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off @@ -93,7 +93,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 40000, + orgAlivePeriod: 100000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -104,7 +104,7 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.0, + orgStepEnergySpendPercent: 0.1, /** * {Number} Percent from orgMaxOrgs config, which is used for crossing borders * between clients/Managers. Entire amount of organisms within one client = @@ -119,7 +119,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 800, /** * {Number} Amount of organisms we have to create on program start */ diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 0c6fffb..6f42730 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -120,7 +120,7 @@ class Organism extends Observer { set mutationPercent(p) {this._mutationPercent = p} set energy(e) {this._energy = e} set startEnergy(e) {this._startEnergy = e} - set changes(c) {this._updateColor(this._changes = c)} + set changes(c) {this._updateColor(c); this._changes = c} /** * Runs one code iteration (amount of lines set in Config.codeYieldPeriod) and returns @@ -263,7 +263,8 @@ class Organism extends Observer { } _updateColor(changes) { - this._color = Organism._getColor(this._colorIndex = Math.round(changes / MAX_BITS)); + this._colorIndex += (changes - this._changes); + this._color = Organism._getColor(Math.round(this._colorIndex / MAX_BITS)); } /** diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 564a3df..19f5215 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -223,7 +223,7 @@ class Organisms extends Configurable { let child = orgs.last.val; if (child.alive && org2.alive) { - child.changes += (child.vm.crossover(org2.vm) * MAX_BITS); + child.changes += (Math.abs(child.vm.crossover(org2.vm)) * MAX_BITS); } } diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index cca2120..4dc5aa6 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -9,6 +9,7 @@ */ const GoogleCharts = require('google-charts').GoogleCharts; const _get = require('lodash/get'); +const Helper = require('./../../../../../../common/src/Helper'); const Config = require('./Config'); class Chart { @@ -67,15 +68,14 @@ class Chart { } _onReady() { - const el = this._el = document.createElement("DIV"); - - el.style.position = 'absolute'; - el.style.opacity = this._cfg.transparent; + document.body.appendChild(this._el = Helper.setStyles('DIV', { + position: 'absolute', + opacity : this._cfg.transparent + })); this._updatePos(this._cfg.pos); - document.body.appendChild(el); - this._ready = true; - this._chart = new google.visualization.LineChart(el); + this._ready = true; + this._chart = new google.visualization.LineChart(this._el); !this._data && (this._data = this._createDataTable()); } @@ -134,13 +134,14 @@ class Chart { _updatePos(pos) { if (!this._el) {return} - const style = this._el.style; - const size = this._getSize(pos); - - style.width = size[0]; - style.height = size[1]; - style.left = size[2]; - style.top = size[3]; + const size = this._getSize(pos); + + Helper.setStyles(this._el, { + width : size[0], + height: size[1], + left : size[2], + top : size[3] + }); } _updateActive(active) { diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index b4f46d1..3087e29 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -4,12 +4,13 @@ * * @author flatline */ -const Status = require('./../Status'); -const Chart = require('./Chart'); -const Config = require('./Config'); const _each = require('lodash/each'); const _has = require('lodash/has'); const _get = require('lodash/get'); +const Helper = require('./../../../../../../common/src/Helper'); +const Status = require('./../Status'); +const Chart = require('./Chart'); +const Config = require('./Config'); const API = { transparent: ['_transparent', 'Sets transparent level' ], @@ -84,9 +85,8 @@ class Charts extends Status { const ips = `ips:${status.ips}`; const pnrg = `pnrg:${status.penergy}`; const code = `cod:${status.code}`; - let header = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; - this._header.textContent = header; + this._header.textContent = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; } _to12h(time) { @@ -100,18 +100,14 @@ class Charts extends Status { } _createHeader() { - const el = this._el = document.createElement("DIV"); - - el.style.position = 'absolute'; - el.style.top = '5px'; - el.style.left = '5px'; - el.style.color = '#fff'; - el.style.fontSize = '18px'; - el.style.fontFamily = 'Consolas'; - - document.body.appendChild(el); - - return el; + return document.body.appendChild(this._el = Helper.setStyles('DIV', { + position : 'absolute', + top : '5px', + left : '5px', + color : '#fff', + fontSize : '18px', + fontFamily: 'Consolas' + })); } /** diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 2ec647c..637e025 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -4,6 +4,7 @@ * @author flatline */ const Panzoom = require('panzoom'); +const Helper = require('./../../../common/src/Helper'); class Canvas { constructor(width, height, noScrolls = false) { @@ -101,17 +102,20 @@ class Canvas { const bodyEl = document.body; const htmlEl = document.querySelector('html'); - bodyEl.style.width = '100%'; - bodyEl.style.height = '100%'; - bodyEl.style.margin = 0; - bodyEl.style.backgroundColor = '#9e9e9e'; - - htmlEl.style.width = '100%'; - htmlEl.style.height = '100%'; - htmlEl.style.margin = 0; + Helper.setStyles(bodyEl, { + width : '100%', + height : '100%', + margin : 0, + backgroundColor: '#9e9e9e' + }); + Helper.setStyles(htmlEl, { + width : '100%', + height : '100%', + margin : 0 + }); - this._ctx.font = "18px Consolas"; - this._ctx.fillStyle = "white"; + this._ctx.font = "18px Consolas"; + this._ctx.fillStyle = "white"; // // This style hides scroll bars on full screen 2d canvas // diff --git a/common/src/Helper.js b/common/src/Helper.js index 10a54c6..6ae7b40 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -3,6 +3,7 @@ * * @author flatline */ +const _each = require('lodash/each'); const Config = require('./../../client/src/share/Config').Config; const DIR = require('./Directions').DIR; @@ -47,6 +48,21 @@ class Helper { obj[fnName] = fn; } + /** + * Apply styles packed in object. key: style name, val: style value + * @param {Element|String} el Element to apply styles or tag name to create + * @param {Object} styles Styles object + * @return {Element} Element with applied styles + */ + static setStyles(el, styles) { + el = typeof el === 'string' ? document.createElement(el) : el; + const style = el.style; + + _each(styles, (val, name) => style[name] = val); + + return el; + } + /** * Sets first letter to lower case * @param {String} s @@ -178,6 +194,10 @@ class Helper { return !isNaN(parseFloat(n)) && isFinite(n); } + static isFunc(v) { + return typeof v === 'function'; + } + /** * Generates unique numeric ids * @returns {Number} @@ -186,10 +206,6 @@ class Helper { return ++this._id; } - static isFunc(v) { - return typeof v === 'function'; - } - // TODO: will be used later // /** // * Saves custom data into the file. If file exists, it will From 803e2eb3bdbbed59f17aa9de3b707bc31ecfc7ac Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 21 Jan 2018 16:14:44 +0200 Subject: [PATCH 146/291] added full screen button at the left top corner --- .../manager/plugins/status/charts/Charts.js | 20 ++++++----- client/src/view/Canvas.js | 35 ++++++++++++++++--- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 3087e29..5710e5f 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -24,9 +24,9 @@ class Charts extends Status { super(manager, Config, API); const periodSec = Config.period / 1000; - this._data = new Array(2); - this._header = this._createHeader(); - this._charts = { + this._data = new Array(2); + this._headerEl = this._createHeader(); + this._charts = { lps : new Chart('LPS - Lines Per Second', Config.charts.lps), ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), orgs : new Chart('Amount of organisms', Config.charts.orgs), @@ -50,8 +50,10 @@ class Charts extends Status { destroy() { _each(this._charts, chart => chart.destroy()); - this._charts = null; - this._data = null; + this._headerEl.parentNode.removeChild(this._headerEl); + this._headerEl = null; + this._charts = null; + this._data = null; super.destroy(); } @@ -86,7 +88,7 @@ class Charts extends Status { const pnrg = `pnrg:${status.penergy}`; const code = `cod:${status.code}`; - this._header.textContent = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; + this._headerEl.textContent = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; } _to12h(time) { @@ -100,10 +102,10 @@ class Charts extends Status { } _createHeader() { - return document.body.appendChild(this._el = Helper.setStyles('DIV', { + return document.body.appendChild(Helper.setStyles('DIV', { position : 'absolute', - top : '5px', - left : '5px', + top : '7px', + left : '35px', color : '#fff', fontSize : '18px', fontFamily: 'Consolas' diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 637e025..3d00721 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -24,6 +24,7 @@ class Canvas { this._animate = this._onAnimate.bind(this); this._visualize = true; this._panZoom = null; + this._fullEl = this._createFullScreen(); this._prepareDom(noScrolls); this._initPanZoomLib(); @@ -32,11 +33,16 @@ class Canvas { } destroy() { + const parentNode = this._canvasEl.parentNode; + this._panZoom.dispose(); - this._canvasEl.parentNode.removeChild(this._canvasEl); - this._ctx = null; - this._imgData = null; - this._data = null; + parentNode.removeChild(this._canvasEl); + parentNode.removeChild(this._fullEl); + this._canvasEl = null; + this._fullEl = null; + this._ctx = null; + this._imgData = null; + this._data = null; } visualize(visualize = true) { @@ -87,6 +93,27 @@ class Canvas { data[offs + 2] = color & 0xff; } + _createFullScreen() { + const el = document.body.appendChild(Helper.setStyles('DIV', { + position : 'absolute', + width : '20px', + height : '20px', + top : '7px', + left : '7px', + border : '1px #000 solid', + backgroundColor: '#f7ed0e', + borderRadius : '6px', + cursor : 'pointer' + })); + + el.onclick = () => { + this._panZoom.zoomAbs(0, 0, 1.0); + this._panZoom.moveTo(0, 0); + }; + + return el; + } + _onAnimate() { const text = this._text; From f36b3fa4f927e27e1caf2b1d7baa5b52360c1811 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 21 Jan 2018 16:18:22 +0200 Subject: [PATCH 147/291] added tooltip for full screen button --- client/src/view/Canvas.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 3d00721..5b7af15 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -106,6 +106,7 @@ class Canvas { cursor : 'pointer' })); + el.title = 'fullscreen'; el.onclick = () => { this._panZoom.zoomAbs(0, 0, 1.0); this._panZoom.moveTo(0, 0); From 634833270e1727ead7b4a2e8acff44edd5f148dd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 21 Jan 2018 22:52:43 +0200 Subject: [PATCH 148/291] tournament principle has returned back killtour chart has returned --- .../src/manager/plugins/organisms/Config.js | 17 +++++--- .../manager/plugins/organisms/Organisms.js | 36 ++++++++++++---- client/src/manager/plugins/status/Status.js | 25 ++++++----- .../manager/plugins/status/charts/Chart.js | 5 +-- .../manager/plugins/status/charts/Charts.js | 1 + .../manager/plugins/status/charts/Config.js | 15 ++++--- .../manager/plugins/status/console/Console.js | 2 +- client/src/share/Events.js | 43 ++++++++++--------- 8 files changed, 88 insertions(+), 56 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 29b6e3b..3b83e72 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -47,16 +47,21 @@ const Config = { * organism after cloning. Should be <= 1.0 (1.0 === 100%) */ orgCloneMutationPercent: 0.0, + /** + * {Boolean} Turn this flag on to give organism a possibility to choose his + * own clone energy and mutations percents. false - mean, that these values + * will be constant for all organisms + */ + orgClonePerOrg: false, /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ orgClonePeriod: 400, /** - * {Boolean} Turn this flag on to give organism a possibility to choose his - * own clone period and percent. false - mean, that these values will be constant - * for all organisms + * {Number} Amount of iterations between tournament. During tournament one + * organism (looser) will be killed */ - orgClonePerOrg: true, + orgTournamentPeriod: 200, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then @@ -123,7 +128,7 @@ const Config = { /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 200, + orgStartAmount: 800, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -174,7 +179,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 40 + codeMaxSize: 60 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 19f5215..5d59075 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -184,6 +184,7 @@ class Organisms extends Configurable { item = item.next; } + this._updateTournament(counter); this._updateClone(counter); this._updateRandomOrgs(counter); this._updateCrossover(counter); @@ -265,19 +266,38 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } + /** + * Does clone of random organism without tournament and removing of extra(overflow) organisms + * @param {Number} counter Current value of counter + * @returns {Boolean} true - clone occurred, false - otherwise + */ _updateClone(counter) { const orgAmount = this.organisms.size; - if (counter % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0 || orgAmount < 1) {return true} - let org1 = this.randOrg(); - if (org1.alive && orgAmount < OConfig.orgMaxOrgs) {this._clone(org1);return} - let org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2) {return false} + if (counter % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0 || orgAmount < 1) {return false} + const org = this.randOrg(); + if (orgAmount < OConfig.orgMaxOrgs && org.alive) {this._clone(org)} - if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + return true; + } - this._clone(org1); - this.parent.fire(EVENTS.KILL_OVERFLOW, org2); + /** + * Does tournament between two random organisms and kill looser. In general + * this function is a natural selection in our system. + * @param {Number} counter Current value of global iterations counter + * @returns {Boolean} true - tournament occurred, false - otherwise + */ + _updateTournament(counter) { + let orgAmount = this.organisms.size; + if (counter % OConfig.orgTournamentPeriod !== 0 || orgAmount < 1 || OConfig.orgTournamentPeriod === 0) {return true} + let org1 = this.randOrg(); + let org2 = this.randOrg(); + if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} + + if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + this.parent.fire(EVENTS.KILL_TOUR, org2); org2.destroy(); + + return true; } _updateRandomOrgs(counter) { diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 8e218af..e269304 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -62,17 +62,19 @@ class Status extends Configurable { this._onEatEnergyCb = this._onEatEnergy.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); - this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 2); - this._onKillEatCb = this._onKillHandlerOrg.bind(this, 3); - this._onKillOverCb = this._onKillHandlerOrg.bind(this, 4); - this._onKillOutCb = this._onKillHandlerOrg.bind(this, 5); - this._onKillInCb = this._onKillHandlerOrg.bind(this, 6); + this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); + this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 3); + this._onKillEatCb = this._onKillHandlerOrg.bind(this, 4); + this._onKillOverCb = this._onKillHandlerOrg.bind(this, 5); + this._onKillOutCb = this._onKillHandlerOrg.bind(this, 6); + this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); + manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); manager.on(EVENTS.KILL_AGE, this._onKillAgeCb); manager.on(EVENTS.KILL_EAT, this._onKillEatCb); @@ -94,12 +96,14 @@ class Status extends Configurable { man.off(EVENTS.KILL_EAT, this._onKillEatCb); man.off(EVENTS.KILL_AGE, this._onKillAgeCb); man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); + man.off(EVENTS.KILL_TOUR, this._onKillTourCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(manager, 'onLoop', this._onLoopCb); this._onKillOrgCb = null; + this._onKillTourCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; this._onKillInCb = null; @@ -167,11 +171,12 @@ class Status extends Configurable { status.kill = fix(this._kill[0], 2); status.killenergy = fix(this._kill[1], 2); - status.killage = fix(this._kill[2], 2); - status.killeat = fix(this._kill[3], 2); - status.killover = fix(this._kill[4], 2); - status.killout = fix(this._kill[5], 2); - status.killin = fix(this._kill[6], 2); + status.killtour = fix(this._kill[2], 2); + status.killage = fix(this._kill[3], 2); + status.killeat = fix(this._kill[4], 2); + status.killover = fix(this._kill[5], 2); + status.killout = fix(this._kill[6], 2); + status.killin = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); !this._firstCall && this.onStatus(status, orgs.size); diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index 4dc5aa6..60715e1 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -84,7 +84,6 @@ class Chart { * [width, height, left, top] * @param {String} pos Position * @returns {Array} [width, height, left, top] - * @private */ _getSize(pos) { return { @@ -148,8 +147,8 @@ class Chart { if (active) { this._onReady(); } else { - this._chart.clearChart(); - this._el.parentNode.removeChild(this._el); + this._chart && this._chart.clearChart(); + this._el && this._el.parentNode.removeChild(this._el); this._chart = this._el = null; } } diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 5710e5f..b589990 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -38,6 +38,7 @@ class Charts extends Status { age : new Chart('Average organism\'s Age', Config.charts.age), code : new Chart('Average organism\'s code size', Config.charts.code), kill : new Chart(`Amount of killed organisms per ${periodSec} sec (all)`, Config.charts.kill), + killtour : new Chart(`Amount of killed organisms in tournament per ${periodSec} sec`, Config.charts.killtour), killenergy: new Chart(`Amount of killed organisms with 0 energy per ${periodSec} sec`, Config.charts.killenergy), killage : new Chart(`Amount of killed organisms with max age per ${periodSec} sec`, Config.charts.killage), killeat : new Chart(`Amount of killed organisms eat by other per ${periodSec} sec`, Config.charts.killeat), diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 2e7501d..fb9b847 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -23,14 +23,15 @@ const Config = { charts: { lps : {pos: 'downleft', active: false, transparent: 0.8}, killout : {pos: 'topright', active: false, transparent: 0.8}, + energy : {pos: 'topdown', active: false, transparent: 0.8}, orgs : {pos: '0-0|16', active: true, transparent: 0.8}, - energy : {pos: '0-1|16', active: true, transparent: 0.8}, - penergy : {pos: '0-2|16', active: true, transparent: 0.8}, - eenergy : {pos: '0-3|16', active: true, transparent: 0.8}, - fit : {pos: '1-0|16', active: true, transparent: 0.8}, - age : {pos: '1-1|16', active: true, transparent: 0.8}, - code : {pos: '1-2|16', active: true, transparent: 0.8}, - kill : {pos: '1-3|16', active: true, transparent: 0.8}, + penergy : {pos: '0-1|16', active: true, transparent: 0.8}, + eenergy : {pos: '0-2|16', active: true, transparent: 0.8}, + fit : {pos: '0-3|16', active: true, transparent: 0.8}, + age : {pos: '1-0|16', active: true, transparent: 0.8}, + code : {pos: '1-1|16', active: true, transparent: 0.8}, + kill : {pos: '1-2|16', active: true, transparent: 0.8}, + killtour : {pos: '1-3|16', active: true, transparent: 0.8}, killenergy: {pos: '2-0|16', active: true, transparent: 0.8}, killage : {pos: '2-1|16', active: true, transparent: 0.8}, killeat : {pos: '2-2|16', active: true, transparent: 0.8}, diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 02609ed..b4839f1 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -48,7 +48,7 @@ class Console extends Status { const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); const senergy = format(status.energy, 'nrg', 17); - const spenergy = format(status.penergy, 'pnrg', 17); + const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); diff --git a/client/src/share/Events.js b/client/src/share/Events.js index e58ccc8..c177cc5 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -15,27 +15,28 @@ const EVENTS = { GRAB_ENERGY : 5, UPDATE_ENERGY : 6, KILL : 7, // general kill event - KILL_NO_ENERGY : 8, // killed if zero energy - KILL_AGE : 9, // killed if max age reached - KILL_EAT : 10, // killed, because other organism has eat this one - KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 12, // killed, because organism step outside the world - KILL_STEP_IN : 13, // killed, because of panishment for step in from near client - KILL_CLONE : 14, // killed, because of lack of energy after clone - MUTATIONS : 15, - EAT : 16, - EAT_ORG : 17, - EAT_ENERGY : 18, - STEP : 19, - STEP_OUT : 20, - STEP_IN : 21, - BORN_ORGANISM : 22, - GET_ENERGY : 23, - DESTROY : 24, - RUN : 25, - STOP : 26, - RESET_CODE : 27, - CHECK_AT : 28 + KILL_TOUR : 8, // killed during organisms tournament + KILL_NO_ENERGY : 9, // killed if zero energy + KILL_AGE : 10, // killed if max age reached + KILL_EAT : 11, // killed, because other organism has eat this one + KILL_OVERFLOW : 12, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 13, // killed, because organism step outside the world + KILL_STEP_IN : 14, // killed, because of panishment for step in from near client + KILL_CLONE : 15, // killed, because of lack of energy after clone + MUTATIONS : 16, + EAT : 17, + EAT_ORG : 18, + EAT_ENERGY : 19, + STEP : 20, + STEP_OUT : 21, + STEP_IN : 22, + BORN_ORGANISM : 23, + GET_ENERGY : 24, + DESTROY : 25, + RUN : 26, + STOP : 27, + RESET_CODE : 28, + CHECK_AT : 29 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; From fd20cffb0207719509ab08535c9ce13c1f9d346a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 22 Jan 2018 01:55:31 +0200 Subject: [PATCH 149/291] new experimental config fixed issue with organisms start color (again) --- client/src/manager/plugins/organisms/Config.js | 10 +++++----- client/src/manager/plugins/organisms/Mutator.js | 5 ++--- client/src/manager/plugins/organisms/Organism.js | 7 +++---- client/src/manager/plugins/organisms/Organisms.js | 5 +++-- client/src/manager/plugins/status/Status.js | 2 +- client/src/manager/plugins/status/charts/Charts.js | 2 +- client/src/manager/plugins/status/charts/Config.js | 2 +- client/src/share/Config.js | 2 +- 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 3b83e72..dbc1695 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -56,18 +56,18 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 400, + orgClonePeriod: 30, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed */ - orgTournamentPeriod: 200, + orgTournamentPeriod: 100, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 20000, + orgRainMutationPeriod: 2000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -88,7 +88,7 @@ const Config = { * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 7000, + orgRandomOrgPeriod: 10000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -98,7 +98,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 100000, + orgAlivePeriod: 10000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 43758a4..95d5b48 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -130,9 +130,8 @@ class Mutator { } _onOrganism(org) { - if (org.iterations % org.mutationPeriod === 0 && OConfig.orgRainMutationPeriod > 0 && OConfig.orgRainMutationPercent > 0.0 && org.mutationPeriod > 0 && org.alive) { - this._mutate(org, false); - } + if (org.iterations % org.mutationPeriod !== 0 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || !org.alive) {return} + this._mutate(org, false); } _onCloneOrg(parent, child) { diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 6f42730..5cee57d 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -236,8 +236,8 @@ class Organism extends Observer { this.vm = new VM(this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; - this._colorIndex = OConfig.orgStartColor; - this._color = Organism._getColor(0); + this._colorIndex = OConfig.orgStartColor * MAX_BITS; + this._color = Organism._getColor(this._colorIndex); this._mutationProbs = OConfig.orgMutationProbs.slice(); this._cloneMutationPercent = OConfig.orgCloneMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; @@ -295,8 +295,7 @@ class Organism extends Observer { return true; } if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - //let grabSize = this.vm.size; - let grabSize = 1; + let grabSize = this.vm.size; if (grabSize < 1) {grabSize = 1} (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 5d59075..3024441 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -324,8 +324,9 @@ class Organisms extends Configurable { if (!org1.alive || !org2.alive) {return false} this._crossover(org1, org2); if (orgAmount + 1 >= OConfig.orgMaxOrgs) { - this.parent.fire(EVENTS.KILL_OVERFLOW, org1); - org1.destroy(); + if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + this.parent.fire(EVENTS.KILL_OVERFLOW, org2); + org2.destroy(); } return true; diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index e269304..a83d5c8 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -162,7 +162,7 @@ class Status extends Configurable { status.lps = fix((this.parent.codeRuns - this._codeRuns) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); - status.penergy = fix(this._pickEnergy, 2); + status.penergy = fix(this._pickEnergy * 10, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); status.changes = +(this._changes).toFixed(1); status.fit = fix(this._fitness / 100, 2); diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index b589990..411e880 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -89,7 +89,7 @@ class Charts extends Status { const pnrg = `pnrg:${status.penergy}`; const code = `cod:${status.code}`; - this._headerEl.textContent = `id:${man.clientId ? man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; } _to12h(time) { diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index fb9b847..c74d21e 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -23,7 +23,7 @@ const Config = { charts: { lps : {pos: 'downleft', active: false, transparent: 0.8}, killout : {pos: 'topright', active: false, transparent: 0.8}, - energy : {pos: 'topdown', active: false, transparent: 0.8}, + energy : {pos: 'downright', active: false, transparent: 0.8}, orgs : {pos: '0-0|16', active: true, transparent: 0.8}, penergy : {pos: '0-1|16', active: true, transparent: 0.8}, eenergy : {pos: '0-2|16', active: true, transparent: 0.8}, diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 51b5af0..cc51c24 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -58,7 +58,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... From 676f8cb0080f01a0c5f2ef511cb8d43b21967f2c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 22 Jan 2018 14:12:52 +0200 Subject: [PATCH 150/291] first good configuration similar to nature :) --- .../src/manager/plugins/organisms/Config.js | 24 +++++++++---------- client/src/share/Config.js | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index dbc1695..3ff5c06 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -56,18 +56,18 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 30, + orgClonePeriod: 10, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed */ - orgTournamentPeriod: 100, + orgTournamentPeriod: 400, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 2000, + orgRainMutationPeriod: 17000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -83,12 +83,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 4000, + orgCrossoverPeriod: 100000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 10000, + orgRandomOrgPeriod: 100000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -98,7 +98,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 10000, + orgAlivePeriod: 18000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -124,34 +124,34 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 800, + orgMaxOrgs: 600, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 800, + orgStartAmount: 600, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 100000, + orgStartEnergy: 500000, /** * {Number} Begin color of "empty". It's just an index of color. Starts from * 0 and till Number.MAX_VALUE */ - orgStartColor: 18, + orgStartColor: 24, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is * 1000, then range will be: -500..500 */ - codeVarInitRange: 100, + codeVarInitRange: 500, /** * {Number} This value is amount of code lines, which will be run for one * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 5, + codeYieldPeriod: 1, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. diff --git a/client/src/share/Config.js b/client/src/share/Config.js index cc51c24..51b5af0 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -58,7 +58,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... From e0998ff7454c229dbaa154609bfbe1870e87110f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 22 Jan 2018 17:32:41 +0200 Subject: [PATCH 151/291] fixed default config --- client/src/manager/plugins/organisms/Config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 3ff5c06..5057c3d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -83,12 +83,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 100000, + orgCrossoverPeriod: 50000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 100000, + orgRandomOrgPeriod: 50000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. From 26045da79c26c9c2cf0eb1288fe01d3d562e62e6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 23 Jan 2018 20:19:03 +0200 Subject: [PATCH 152/291] added zoom speed option (Config.worldZoomSpeed) changed default config --- client/src/manager/plugins/organisms/Config.js | 12 ++++++------ client/src/share/Config.js | 4 ++++ client/src/view/Canvas.js | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5057c3d..27ddaac 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -31,7 +31,7 @@ const Config = { * copy - Probability of copying of code lines inside it's own code * ] */ - orgMutationProbs: [1,1,90,1,1,1,1,1,10,1], + orgMutationProbs: [10,1,90,1,1,1,1,1,10,5], /** * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant @@ -83,12 +83,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 50000, + orgCrossoverPeriod: 40000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 50000, + orgRandomOrgPeriod: 40000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -124,11 +124,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 600, + orgMaxOrgs: 800, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 600, + orgStartAmount: 800, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -151,7 +151,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 1, + codeYieldPeriod: 4, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 51b5af0..fc8f3bb 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -87,6 +87,10 @@ ClientConfig.init({ * {Boolean} Turns on/off scroll bars in a 2D canvas */ worldNoScrolls: true, + /** + * {Number} Zoom speed 0..1 + */ + worldZoomSpeed: 0.05, /** * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 5b7af15..ce83c7f 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -5,6 +5,7 @@ */ const Panzoom = require('panzoom'); const Helper = require('./../../../common/src/Helper'); +const Config = require('./../share/Config').Config; class Canvas { constructor(width, height, noScrolls = false) { @@ -158,7 +159,7 @@ class Canvas { _initPanZoomLib() { this._canvasEl.style.imageRendering = 'pixelated'; this._panZoom = Panzoom(this._canvasEl, { - zoomSpeed : 0.05, + zoomSpeed : Config.worldZoomSpeed, smoothScroll: false }); this._panZoom.zoomAbs(0, 0, 1.0); From 6b92d991e4c2fd5e15b8e21b1aabd7e12b1a8e74 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 25 Jan 2018 12:00:51 +0200 Subject: [PATCH 153/291] new default configuration --- client/src/manager/plugins/organisms/Config.js | 12 ++++++------ client/src/share/Config.js | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 27ddaac..4411648 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -61,13 +61,13 @@ const Config = { * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed */ - orgTournamentPeriod: 400, + orgTournamentPeriod: 50, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 17000, + orgRainMutationPeriod: 10000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -83,12 +83,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 40000, + orgCrossoverPeriod: 2000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 40000, + orgRandomOrgPeriod: 2000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -124,11 +124,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 800, + orgMaxOrgs: 10000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 800, + orgStartAmount: 5000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/share/Config.js b/client/src/share/Config.js index fc8f3bb..5065321 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -45,11 +45,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920, + worldWidth: 5760, /** * {Number} World height */ - worldHeight: 1080, + worldHeight: 3240, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -63,7 +63,7 @@ ClientConfig.init({ * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... */ - worldEnergyDots: 1000, + worldEnergyDots: 10000, /** * {Number} Amount of energy in every block. See worldEnergyDots * config for details. @@ -76,13 +76,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.2, + worldEnergyCheckPercent: 0.3, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 1000, + worldEnergyCheckPeriod: 200, /** * {Boolean} Turns on/off scroll bars in a 2D canvas */ From 7dffb114b33b4ef50d583a02cf07a086507d765f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 26 Jan 2018 01:04:22 +0200 Subject: [PATCH 154/291] added weight of operators (see OConfig.orgOperatorWeights) #2 speed optimization of Observer class --- .../src/manager/plugins/organisms/Config.js | 22 +++++++-- .../plugins/organisms/dos/Operators.js | 46 ++++++++++++------- common/src/Observer.js | 6 ++- 3 files changed, 51 insertions(+), 23 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4411648..56f8a8a 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -9,6 +9,18 @@ const Config = { * range: [0...ORG_MUTATION_PROBS_MAX_VAL] including these values */ ORG_MUTATION_PROBS_MAX_VAL: 100, + /** + * {Array} Array of operators weights in energy equivalent. Every value of this + * array is bind to special operator run on VM. The same sequence should be + * implemented. See Operators.operators getter for details. Values may be float. + * Values titles: + * [ + * onVar,onCondition,onLoop,omOperator,onLookAt,onEatLeft,onEatRight,onEatUp, + * onEatDown,onStepLeft,onStepRight,onStepUp,onStepDown,onFromMem,onToMem, + * onMyX,onMyY,onCheckLeft,onCheckRight,onCheckUp,onCheckDown + * ] + */ + orgOperatorWeights: [.1,.1,.001,.1,.01,.2,.2,.2,.2,.5,.5,.5,.5,.1,.1,.1,.1,.1,.1,.1,.1], /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of @@ -56,18 +68,18 @@ const Config = { /** * {Number} Amount of iterations between cloning. Set it to 0 to turn it off */ - orgClonePeriod: 10, + orgClonePeriod: 2, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed */ - orgTournamentPeriod: 50, + orgTournamentPeriod: 0, /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 10000, + orgRainMutationPeriod: 3000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -93,12 +105,12 @@ const Config = { * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. */ - orgEnergySpendPeriod: 10, + orgEnergySpendPeriod: 0, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 18000, + orgAlivePeriod: 10000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 4178291..748f066 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -94,10 +94,12 @@ class OperatorsDos extends Operators { * * @param {Number} num Packed into number vm line * @param {Number} line Current line in vm + * @param {Organism} org Current organism * @return {Number} Parsed vm line string */ - onVar(num, line) { + onVar(num, line, org) { this.vars[VAR0(num)] = VAR2(num) < HALF_OF_VAR ? BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : this.vars[VAR1(num)]; + org.grabEnergy(OConfig.orgOperatorWeights[0]); return ++line; } @@ -111,9 +113,11 @@ class OperatorsDos extends Operators { const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); if (CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { + org.grabEnergy(OConfig.orgOperatorWeights[1]); return ++line; } + org.grabEnergy(OConfig.orgOperatorWeights[1]); return offs; } @@ -132,8 +136,11 @@ class OperatorsDos extends Operators { if (afterIteration === true) { if (++vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); + org.grabEnergy(OConfig.orgOperatorWeights[2]); return ++line; } + + org.grabEnergy(OConfig.orgOperatorWeights[2]); return offs; } // @@ -143,15 +150,18 @@ class OperatorsDos extends Operators { vars[var0] = vars[VAR1(num)]; if (vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); + org.grabEnergy(OConfig.orgOperatorWeights[2]); return ++line; } + org.grabEnergy(OConfig.orgOperatorWeights[2]); return offs; } - onOperator(num, line) { + onOperator(num, line, org) { const vars = this.vars; vars[VAR0(num)] = OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); + org.grabEnergy(OConfig.orgOperatorWeights[3]); return ++line; } @@ -177,6 +187,7 @@ class OperatorsDos extends Operators { if (!IS_NUM(x) || !IS_NUM(y) || Helper.normalize(x, y)[2] !== DIR.NO) { vars[VAR0(num)] = 0; + org.grabEnergy(OConfig.orgOperatorWeights[4]); return ++line; } @@ -184,35 +195,38 @@ class OperatorsDos extends Operators { this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); vars[VAR0(num)] = ret.ret; + org.grabEnergy(OConfig.orgOperatorWeights[4]); return ++line; } - onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); return ++line} - onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); return ++line} - onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} - onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} + onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[5]); return ++line} + onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[6]); return ++line} + onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); org.grabEnergy(OConfig.orgOperatorWeights[7]); return ++line} + onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); org.grabEnergy(OConfig.orgOperatorWeights[8]); return ++line} - onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; return ++line} - onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; return ++line} - onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; return ++line} - onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} + onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.grabEnergy(OConfig.orgOperatorWeights[9]); return ++line} + onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.grabEnergy(OConfig.orgOperatorWeights[10]); return ++line} + onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.grabEnergy(OConfig.orgOperatorWeights[11]); return ++line} + onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.grabEnergy(OConfig.orgOperatorWeights[12]); return ++line} onFromMem(num, line, org) { this.vars[VAR0(num)] = org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; + org.grabEnergy(OConfig.orgOperatorWeights[13]); return ++line; } onToMem(num, line, org) { org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[VAR0(num)]; + org.grabEnergy(OConfig.orgOperatorWeights[14]); return ++line; } - onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; return ++line} - onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; return ++line} + onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; org.grabEnergy(OConfig.orgOperatorWeights[15]); return ++line} + onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; org.grabEnergy(OConfig.orgOperatorWeights[16]); return ++line} - onCheckLeft(num, line, org) {return this._checkAt(num, line, org, org.x - 1, org.y)} - onCheckRight(num, line, org) {return this._checkAt(num, line, org, org.x + 1, org.y)} - onCheckUp(num, line, org) {return this._checkAt(num, line, org, org.x, org.y - 1)} - onCheckDown(num, line, org) {return this._checkAt(num, line, org, org.x, org.y + 1)} + onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[17]); return energy} + onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[18]); return energy} + onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.grabEnergy(OConfig.orgOperatorWeights[19]); return energy} + onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.grabEnergy(OConfig.orgOperatorWeights[20]); return energy} _checkAt(num, line, org, x, y) { const ret = {ret: 0}; diff --git a/common/src/Observer.js b/common/src/Observer.js index ea1c2e9..ea64fc5 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -51,8 +51,10 @@ class Observer { * @param args */ fire (event, ...args) { - let handlers = this._handlers[event] || []; - for (let handler of handlers) {handler(...args)} + const handlers = this._handlers[event] || []; + for (let i = 0, len = handlers.length; i < len; i++) { + handlers[i](...args); + } } /** From 86207e9ef6f0a524e3717f4ac9f6b87ca439288e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 26 Jan 2018 01:19:13 +0200 Subject: [PATCH 155/291] small speed optimization --- client/src/manager/plugins/organisms/Organism.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 5cee57d..b4d78ee 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -201,7 +201,7 @@ class Organism extends Observer { } grabEnergy(amount) { - if (!IS_NUM(amount)) {return true} + if (!IS_NUM(amount) || amount === 0) {return true} const noEnergy = (this._energy -= amount) < 1; this.fire(GRAB_ENERGY, amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); From 03060b992371d8799abcb6ebde511087b17f86d8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 26 Jan 2018 09:42:10 +0200 Subject: [PATCH 156/291] added on/off for charts --- .../manager/plugins/status/charts/Charts.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 411e880..8bdd424 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -16,6 +16,8 @@ const API = { transparent: ['_transparent', 'Sets transparent level' ], pos : ['_pos', 'Sets chart position' ], active : ['_active', 'Activates/Deactivates chart'], + on : ['_on', 'Activates/Deactivates chart'], + off : ['_off', 'Deactivates chart' ], reset : ['_reset', 'Resets chart data' ] }; @@ -163,6 +165,25 @@ class Charts extends Status { } } + /** + * Shortcut for _active() method. See it for details. + */ + _on(...args) { + this._active(...args) + } + + /** + * Opposite to _on(). + * @param {String=} chart Chart name + */ + _off(chart) { + if (typeof chart === 'string') { + this._active(chart, false); + } else { + this._active(false); + } + } + /** * Resets chart data. It means, that chart will be refreshed with * data started from this moment and further. You may call this From 8cf31a027df25bf51c1d2d84b18430848c6f9a2c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Feb 2018 00:29:26 +0200 Subject: [PATCH 157/291] removed cloneMutationPercent. it has no sense (always 0.5 from now) refactored events to callbacks many small refactoring provided new approach for organisms diversity removed mutation of clone period and percent added orgCloneMinEnergy config added orgKillOnClone config removed orgClonePeriod config removed orgClonePerOrg config removed orgCloneMutationPercent config removed mutations on clone approach changed basic fitness function iterations of organisms start from 0 (not 1) fixed few issues in VM --- client/src/manager/Manager.js | 3 +- client/src/manager/plugins/backup/Backup.js | 1 - .../src/manager/plugins/organisms/Config.js | 42 +++++------ .../src/manager/plugins/organisms/Mutator.js | 33 ++------- .../src/manager/plugins/organisms/Organism.js | 55 ++++++++------ .../manager/plugins/organisms/Organisms.js | 72 ++++++++++--------- .../plugins/organisms/dos/Operators.js | 40 +++++++---- .../manager/plugins/organisms/dos/Organism.js | 5 +- .../plugins/organisms/dos/Organisms.js | 66 ++++++++++------- .../plugins/organisms/garmin/Operators.js | 6 +- .../plugins/organisms/garmin/Organism.js | 7 +- .../plugins/organisms/garmin/Organisms.js | 7 +- client/src/manager/plugins/status/Status.js | 2 +- client/src/share/Config.js | 14 ++-- client/src/vm/Operators.js | 16 ++--- client/src/vm/VM.js | 13 ++-- 16 files changed, 198 insertions(+), 184 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index c5c2ae8..7a35fb4 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -251,6 +251,7 @@ class Manager extends Observer { * (onIteration()) inside by calling this.zeroTimeout(). */ _onLoop () { + if (!this._active) {return} // // This conditions id needed for turned on visualization mode to // prevent flickering of organisms in a canvas. It makes their @@ -264,7 +265,7 @@ class Manager extends Observer { this.onIteration(i, TIMER()); } this.onLoop(this._counter = i, TIMER()); - this._active && this.zeroTimeout(this._onLoopCb); + this.zeroTimeout(this._onLoopCb); } _addHandlers() { diff --git a/client/src/manager/plugins/backup/Backup.js b/client/src/manager/plugins/backup/Backup.js index 91f91ee..61691f6 100644 --- a/client/src/manager/plugins/backup/Backup.js +++ b/client/src/manager/plugins/backup/Backup.js @@ -61,7 +61,6 @@ class Backup { x : org.x, y : org.y, mutationProbs : org.mutationProbs, - cloneMutationPercent: org.cloneMutationPercent, mutationPeriod : org.mutationPeriod, mutationPercent : org.mutationPercent, color : org.color, diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 56f8a8a..47e63e6 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -20,7 +20,7 @@ const Config = { * onMyX,onMyY,onCheckLeft,onCheckRight,onCheckUp,onCheckDown * ] */ - orgOperatorWeights: [.1,.1,.001,.1,.01,.2,.2,.2,.2,.5,.5,.5,.5,.1,.1,.1,.1,.1,.1,.1,.1], + orgOperatorWeights: [.1,.1,.001,.1,.01,2.,2.,2.,2.,2.,2.,2.,2.,.1,.1,.1,.1,.1,.1,.1,.1], /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of @@ -34,16 +34,14 @@ const Config = { * change - Probability of changing existing line of code * delete - Probability of deleting a line of code * small-change - Probability of "small change" - change part of one code line - * clone - Probability for sharing of energy percent on clone * period - Probability of period of organism mutations * amount - Probability of amount of mutations per period * probs - Probability of change one of probability coefficient in this array - * clone-percent - Probability of change clone energy percent value * add - Probability of adding new line to the code * copy - Probability of copying of code lines inside it's own code * ] */ - orgMutationProbs: [10,1,90,1,1,1,1,1,10,5], + orgMutationProbs: [5,1,90,1,1,1,20,1], /** * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant @@ -55,20 +53,18 @@ const Config = { */ orgCloneEnergyPercent: 0.5, /** - * {Number} Percent of mutations from vm size, which will be applied to - * organism after cloning. Should be <= 1.0 (1.0 === 100%) + * {Number} Minimum energy for one organism, which will be multiplied on + * organism code size. This value permits organism to have a baby (clone). + * If amount of energy less then orgCloneMinEnergy * vm.size, then clone + * is not possible */ - orgCloneMutationPercent: 0.0, + orgCloneMinEnergy: 1000, /** - * {Boolean} Turn this flag on to give organism a possibility to choose his - * own clone energy and mutations percents. false - mean, that these values - * will be constant for all organisms - */ - orgClonePerOrg: false, - /** - * {Number} Amount of iterations between cloning. Set it to 0 to turn it off + * {Boolean} true means, that one organism will be killed just after new + * organism has cloned. If population is less then orgMaxOrgs, then no killing + * will be provided. Killing of organism will be done using tournament approach */ - orgClonePeriod: 2, + orgKillOnClone: false, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -79,7 +75,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 3000, + orgRainMutationPeriod: 10000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -95,12 +91,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 2000, + orgCrossoverPeriod: 10000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 2000, + orgRandomOrgPeriod: 10000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -110,7 +106,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 10000, + orgAlivePeriod: 0, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -136,17 +132,17 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 10000, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 5000, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 500000, + orgStartEnergy: 10000000, /** * {Number} Begin color of "empty". It's just an index of color. Starts from * 0 and till Number.MAX_VALUE @@ -191,7 +187,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 60 + codeMaxSize: 300 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 95d5b48..0876c24 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -20,7 +20,7 @@ const MAX_VAR = Num.MAX_VAR; const MAX_BITS = Num.MAX_BITS; const BITS_PER_VAR = Num.BITS_PER_VAR; -const ADD_MUTAION_INDEX = 8; +const ADD_MUTAION_INDEX = 6; class Mutator { static _onChange(org) { @@ -75,18 +75,6 @@ class Mutator { org.changes++; } - static _onCloneMutationPercent(org) { - if (!OConfig.orgClonePerOrg) {return} - org.cloneMutationPercent = Math.random(); - org.changes++; - } - - static _onCloneEnergyPercent(org) { - if (!OConfig.orgClonePerOrg) {return} - org.cloneEnergyPercent = Math.random(); - org.changes++; - } - static _onAdd(org) { org.vm.insertLine(); org.changes += MAX_BITS; @@ -106,23 +94,17 @@ class Mutator { Mutator._onMutationPeriod, Mutator._onMutationPercent, Mutator._onProbs, - Mutator._onCloneMutationPercent, - Mutator._onCloneEnergyPercent, Mutator._onAdd, Mutator._onCopy ]; this._onOrganismCb = this._onOrganism.bind(this); - this._onCloneCb = this._onCloneOrg.bind(this); Helper.override(owner, 'onOrganism', this._onOrganismCb); - Helper.override(owner, 'onClone', this._onCloneCb); } destroy() { - Helper.unoverride(this._owner, 'onClone', this._onCloneCb); Helper.unoverride(this._owner, 'onOrganism', this._onOrganismCb); - this._onCloneCb = null; this._onOrganismCb = null; this._manager = null; this._owner = null; @@ -131,25 +113,20 @@ class Mutator { _onOrganism(org) { if (org.iterations % org.mutationPeriod !== 0 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || !org.alive) {return} - this._mutate(org, false); - } - - _onCloneOrg(parent, child) { - if (child.energy > 0 && OConfig.orgCloneMutationPercent > 0.0 && OConfig.orgClonePeriod > 0) {this._mutate(child)} + this._mutate(org); } /** * IMPORTANT: mutations should be applied only after last line of organism's code * has interpreted * @param {Organism} org Current organism - * @param {Boolean} clone true if mutation is applying after clone */ - _mutate(org, clone = true) { + _mutate(org) { const vm = org.vm; const probIndex = Helper.probIndex; const mTypes = this._MUTATION_TYPES; const maxSize = OConfig.codeMaxSize; - let mutations = Math.round(vm.size * (clone ? org.cloneMutationPercent : org.mutationPercent)) || 1; + let mutations = Math.round(vm.size * org.mutationPercent) || 1; let type; for (let i = 0; i < mutations; i++) { @@ -161,7 +138,7 @@ class Mutator { if (vm.size >= maxSize && type >= ADD_MUTAION_INDEX) {mutations = i; break} mTypes[type](org); } - this._manager.fire(EVENTS.MUTATIONS, org, mutations, clone); + this._manager.fire(EVENTS.MUTATIONS, org, mutations); } } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index b4d78ee..a1167cb 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -39,7 +39,7 @@ class Organism extends Observer { * @returns {Number} RGB value */ static _getColor(index) { - const frequency = 0.1; + const frequency = 0.05; const r = Math.sin(frequency * index ) * 127 + 128; const g = Math.sin(frequency * index + 2) * 127 + 128; @@ -73,20 +73,22 @@ class Organism extends Observer { * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Function} operatorCls Class of operators + * @param {Object} callbacks Map of callback functions * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, operatorCls, parent = null) { + constructor(id, x, y, alive, item, operatorCls, callbacks, parent = null) { super(EVENT_AMOUNT); this._operatorCls = operatorCls; + this._callbacks = callbacks; if (parent === null) {this._create()} else {this._clone(parent)} - this._id = id; this._x = x; this._y = y; - this._iterations = 0; + this._iterations = -1; + this._nextClone = this._energy + OConfig.orgCloneMinEnergy; this._changes = 0; this._alive = alive; this._item = item; @@ -103,7 +105,6 @@ class Organism extends Observer { get mutationProbs() {return this._mutationProbs} get mutationPeriod() {return this._mutationPeriod} get mutationPercent() {return this._mutationPercent} - get cloneMutationPercent() {return this._cloneMutationPercent} get cloneEnergyPercent() {return this._cloneEnergyPercent} get energy() {return this._energy} get startEnergy() {return this._startEnergy} @@ -111,10 +112,10 @@ class Organism extends Observer { get colorIndex() {return this._colorIndex} get mem() {return this._mem} get posId() {return Helper.posId(this._x, this._y)} + get callbacks() {return this._callbacks} set x(newX) {this._x = newX} set y(newY) {this._y = newY} - set cloneMutationPercent(m) {this._cloneMutationPercent = m} set cloneEnergyPercent(p) {this._cloneEnergyPercent = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} @@ -130,10 +131,15 @@ class Organism extends Observer { run() { this._iterations++; if (this.onBeforeRun() === false) {return true} - const lines = this.onRun(); - - this.fire(ITERATION, lines, this); + // + // IMPORTANT: cloning must be before onRun() to prevent + // IMPORTANT: app hang (very long loops), when organism + // IMPORTANT: eats itself) + // + this._alive && this._updateClone(); + const lines = this._alive ? this.onRun() : 0; if (this._alive) { + this._callbacks[ITERATION](lines, this); this._alive && this._updateAge(); this._alive && this._updateEnergy(); } @@ -154,6 +160,7 @@ class Organism extends Observer { alive : this._alive, // 'item' will be added after insertion iterations : this._iterations, + nextClone : this._nextClone, fnId : this._fnId, vm : this.vm.serialize(), energy : this._energy, @@ -161,7 +168,6 @@ class Organism extends Observer { color : this._color, colorIndex : this._colorIndex, mutationProbs : this._mutationProbs, - cloneMutationPercent: this._cloneMutationPercent, cloneEnergyPercent : this._cloneEnergyPercent, mutationPeriod : this._mutationPeriod, mutationPercent : this._mutationPercent, @@ -186,6 +192,7 @@ class Organism extends Observer { this._alive = json.alive; // 'item' will be added after insertion this._iterations = json.iterations; + this._nextClone = json.nextClone; this._fnId = json.fnId; this.vm.unserialize(json.vm); this._energy = json.energy; @@ -193,7 +200,6 @@ class Organism extends Observer { this._color = json.color; this._colorIndex = json.colorIndex; this._mutationProbs = json.mutationProbs; - this._cloneMutationPercent = json.cloneMutationPercent; this._cloneEnergyPercent = json.cloneEnergyPercent; this._mutationPeriod = json.mutationPeriod; this._mutationPercent = json.mutationPercent; @@ -203,7 +209,7 @@ class Organism extends Observer { grabEnergy(amount) { if (!IS_NUM(amount) || amount === 0) {return true} const noEnergy = (this._energy -= amount) < 1; - this.fire(GRAB_ENERGY, amount + (noEnergy ? -this._energy : 0)); + this._callbacks && this._callbacks[GRAB_ENERGY](amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); return !noEnergy; } @@ -214,11 +220,11 @@ class Organism extends Observer { //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); //return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); - return this._energy; + return this._energy / (this.vm.size || 1); } destroy() { - this.fire(DESTROY, this); + this._callbacks[DESTROY](this); this._alive = false; this._energy = 0; this._startEnergy = 0; @@ -228,18 +234,20 @@ class Organism extends Observer { this.vm && this.vm.destroy(); this.vm = null; this._operatorCls = null; + this._callbacks = null; + this._nextClone = null; + this._iterations = -1; super.destroy(); } _create() { - this.vm = new VM(this, this._operatorCls); + this.vm = new VM(this._callbacks, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; this._colorIndex = OConfig.orgStartColor * MAX_BITS; this._color = Organism._getColor(this._colorIndex); this._mutationProbs = OConfig.orgMutationProbs.slice(); - this._cloneMutationPercent = OConfig.orgCloneMutationPercent; this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; @@ -249,13 +257,12 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this, this._operatorCls, parent.vm); + this.vm = new VM(this._callbacks, this._operatorCls, parent.vm); this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; this._colorIndex = parent.colorIndex; this._mutationProbs = parent.mutationProbs.slice(); - this._cloneMutationPercent = parent.cloneMutationPercent; this._cloneEnergyPercent = parent.cloneEnergyPercent; this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; @@ -267,6 +274,12 @@ class Organism extends Observer { this._color = Organism._getColor(Math.round(this._colorIndex / MAX_BITS)); } + _updateClone() { + if ((this._energy > this._nextClone) && this.vm.size > 0 && this._callbacks[CLONE](this) && this._alive) { + this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1); + } + } + /** * Checks if organism need to be killed, because of age * @return {Boolean} false means that organism was killed. @@ -276,7 +289,7 @@ class Organism extends Observer { const needDestroy = this._iterations >= alivePeriod && alivePeriod > 0; if (needDestroy) { - this.fire(KILL_AGE, this); + this._callbacks[KILL_AGE](this); this.destroy(); } @@ -290,7 +303,7 @@ class Organism extends Observer { */ _updateEnergy() { if (this._energy < 1) { - this.fire(KILL_NO_ENERGY, this); + this._callbacks[KILL_NO_ENERGY](this); this.destroy(); return true; } @@ -298,7 +311,7 @@ class Organism extends Observer { let grabSize = this.vm.size; if (grabSize < 1) {grabSize = 1} - (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); + (this._energy <= grabSize) && this._callbacks[KILL_NO_ENERGY](this); return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 3024441..6ca9727 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -87,6 +87,7 @@ class Organisms extends Configurable { this.randOrgItem = this.organisms.first; this.positions = manager.positions; this.world = manager.world; + const cbs = this.callbacks = {}; this._mutator = new Mutator(manager, this); this._onIterationCb = this._onIteration.bind(this); @@ -95,6 +96,14 @@ class Organisms extends Configurable { this.reset(); Helper.override(manager, 'onIteration', this._onIterationCb); Helper.override(manager, 'onLoop', this._onLoopCb); + + cbs[ORG_EVENTS.DESTROY] = this._onKillOrg.bind(this); + cbs[ORG_EVENTS.KILL_NO_ENERGY] = this._onKillNoEnergyOrg.bind(this); + cbs[ORG_EVENTS.KILL_AGE] = this._onKillAgeOrg.bind(this); + cbs[ORG_EVENTS.ITERATION] = this._onIterationOrg.bind(this); + cbs[ORG_EVENTS.CLONE] = this._onCloneOrg.bind(this); + cbs[ORG_EVENTS.GRAB_ENERGY] = () => {}; + } destroy() { @@ -108,17 +117,11 @@ class Organisms extends Configurable { this._mutator = null; this._onIterationCb = null; this._onLoopCb = null; + this.callbacks = null; super.destroy(); } - addOrgHandlers(org) { - org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); - org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); - org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); - org.on(ORG_EVENTS.ITERATION, this._onIterationOrg.bind(this)); - } - reset() { this._orgId = 0; } @@ -136,14 +139,13 @@ class Organisms extends Configurable { } createOrg(pos, parent = null) { - const orgs = this.organisms; if (pos === false) {return false} + const orgs = this.organisms; orgs.add(null); - let last = orgs.last; - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, parent); + let last = orgs.last; + let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, this.callbacks, parent); last.val = org; - this.addOrgHandlers(org); this.move(-1, -1, pos.x, pos.y, org); this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); @@ -175,17 +177,17 @@ class Organisms extends Configurable { * @param {Number} stamp Time stamp of current iteration */ _onIteration(counter, stamp) { - let item = this.organisms.first; - let org; + const onOrganism = this.onOrganism.bind(this); + let item = this.organisms.first; + let org; while (org = item && item.val) { org.run(); - this.onOrganism(org); + onOrganism(org); item = item.next; } this._updateTournament(counter); - this._updateClone(counter); this._updateRandomOrgs(counter); this._updateCrossover(counter); } @@ -213,6 +215,7 @@ class Organisms extends Configurable { let child = this.organisms.last.val; this.onClone(org, child); + if (!org.alive || !child.alive) {return false} this.parent.fire(EVENTS.CLONE, org, child); return true; @@ -266,16 +269,24 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - /** - * Does clone of random organism without tournament and removing of extra(overflow) organisms - * @param {Number} counter Current value of counter - * @returns {Boolean} true - clone occurred, false - otherwise - */ - _updateClone(counter) { + _onCloneOrg(org) { + const maxOrgs = OConfig.orgMaxOrgs; const orgAmount = this.organisms.size; - if (counter % OConfig.orgClonePeriod !== 0 || OConfig.orgClonePeriod === 0 || orgAmount < 1) {return false} - const org = this.randOrg(); - if (orgAmount < OConfig.orgMaxOrgs && org.alive) {this._clone(org)} + const ret = org.alive && (OConfig.orgKillOnClone || orgAmount < maxOrgs) && this._clone(org); + + if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this._killInTour()} + + return ret; + } + + _killInTour() { + let org1 = this.randOrg(); + let org2 = this.randOrg(); + if (!org1.alive || !org2.alive || org1 === org2 || this.organisms.size < 1) {return false} + + if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + this.parent.fire(EVENTS.KILL_TOUR, org2); + org2.destroy(); return true; } @@ -287,17 +298,8 @@ class Organisms extends Configurable { * @returns {Boolean} true - tournament occurred, false - otherwise */ _updateTournament(counter) { - let orgAmount = this.organisms.size; - if (counter % OConfig.orgTournamentPeriod !== 0 || orgAmount < 1 || OConfig.orgTournamentPeriod === 0) {return true} - let org1 = this.randOrg(); - let org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2 || orgAmount < 1) {return false} - - if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} - this.parent.fire(EVENTS.KILL_TOUR, org2); - org2.destroy(); - - return true; + const period = OConfig.orgTournamentPeriod; + return counter % period === 0 && this.organisms.size > 0 || period !== 0 && this._killInTour(); } _updateRandomOrgs(counter) { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 748f066..8346f21 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -13,6 +13,11 @@ const OConfig = require('./../Config'); const Operators = require('./../../../../vm/Operators'); const Num = require('./../../../../vm/Num'); +/** + * {Function} Is created to speed up this function call. constants are run + * much faster, then Helper.normalize() + */ +const NORMALIZE = Helper.normalize; /** * {Function} Just a shortcuts */ @@ -39,8 +44,8 @@ const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; class OperatorsDos extends Operators { - constructor(offs, vars, obs) { - super(offs, vars, obs); + constructor(offs, vars, callbacks) { + super(offs, vars, callbacks); /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -72,6 +77,10 @@ class OperatorsDos extends Operators { this.onCheckUp.bind(this), this.onCheckDown.bind(this) ]; + /** + * {Object} Reusable object to pass it as a parameter to this.callbacks(..., ret) + */ + this._ret = {ret: 0, x: 0, y: 0}; //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // // We have to set amount of available operators for correct @@ -185,14 +194,15 @@ class OperatorsDos extends Operators { let x = vars[VAR1(num)]; let y = vars[VAR2(num)]; - if (!IS_NUM(x) || !IS_NUM(y) || Helper.normalize(x, y)[2] !== DIR.NO) { + if (!IS_NUM(x) || !IS_NUM(y) || NORMALIZE(x, y)[2] !== DIR.NO) { vars[VAR0(num)] = 0; org.grabEnergy(OConfig.orgOperatorWeights[4]); return ++line; } - let ret = {ret: 0}; - this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); + const ret = this._ret; + ret.ret = 0; + this.callbacks[EVENTS.GET_ENERGY](org, x, y, ret); vars[VAR0(num)] = ret.ret; org.grabEnergy(OConfig.orgOperatorWeights[4]); @@ -229,29 +239,31 @@ class OperatorsDos extends Operators { onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.grabEnergy(OConfig.orgOperatorWeights[20]); return energy} _checkAt(num, line, org, x, y) { - const ret = {ret: 0}; - org.fire(EVENTS.CHECK_AT, x, y, ret); + const ret = this._ret; + + ret.ret = 0; + this.callbacks[EVENTS.CHECK_AT](x, y, ret); this.vars[VAR0(num)] = ret.ret; return ++line; } _eat(org, num, x, y) { - const vars = this.vars; - const amount = vars[VAR1(num)]; + const amount = this.vars[VAR1(num)]; if (!IS_NUM(amount) || amount === 0) {return 0} + const ret = this._ret; - let ret = {ret: amount}; - this.obs.fire(EVENTS.EAT, org, x, y, ret); - if (!IS_NUM(ret.ret) || ret.ret === 0) {return 0} + if ((ret.ret = amount) <= 0) {return 0} + this.callbacks[EVENTS.EAT](org, x, y, ret); org.energy += ret.ret; return ret.ret; } _step(org, x1, y1, x2, y2) { - let ret = {ret: 0}; + const ret = this._ret; - this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2, ret); + ret.ret = 0; + this.callbacks[EVENTS.STEP](org, x1, y1, x2, y2, ret); if (ret.ret > 0) { org.x = ret.x; org.y = ret.y; diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 7ba1446..e895369 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -17,10 +17,11 @@ class OrganismDos extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located + * @param {Object} callbacks Map of callback functions * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, parent = null) { - super(id, x, y, alive, item, Operators, parent); + constructor(id, x, y, alive, item, callbacks, parent = null) { + super(id, x, y, alive, item, Operators, callbacks, parent); } onRun() { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 4a648fd..847663d 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -17,12 +17,29 @@ const OConfig = require('./../Config'); const EVENTS = require('./../../../../share/Events').EVENTS; const Helper = require('./../../../../../../common/src/Helper'); const DIR = require('./../../../../../../common/src/Directions').DIR; +/** + * {Function} Is created to speed up this function call. constants are run + * much faster, then Helper.normalize() + */ +const NORMALIZE = Helper.normalize; +/** + * {Function} Is created to speed up this function call. constants are run + * much faster, then Helper.posId() + */ +const POSID = Helper.posId; class Organisms extends BaseOrganisms { constructor(manager) { super(manager); this._onStepInCb = this._onStepIn.bind(this); + this.parent.on(EVENTS.STEP_IN, this._onStepInCb); + + const cbs = this.callbacks; + cbs[EVENTS.GET_ENERGY] = this._onGetEnergy.bind(this); + cbs[EVENTS.EAT] = this._onEat.bind(this); + cbs[EVENTS.STEP] = this._onStep.bind(this); + cbs[EVENTS.CHECK_AT] = this._onCheckAt.bind(this); } destroy() { @@ -79,14 +96,6 @@ class Organisms extends BaseOrganisms { child.alive && (child.startEnergy = child.energy); } - addOrgHandlers(org) { - super.addOrgHandlers(org); - org.on(EVENTS.GET_ENERGY, this._onGetEnergy.bind(this)); - org.on(EVENTS.EAT, this._onEat.bind(this)); - org.on(EVENTS.STEP, this._onStep.bind(this)); - org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); - } - /** * Creates instance of an organism * @param {Array} args Custom organism arguments @@ -119,8 +128,8 @@ class Organisms extends BaseOrganisms { */ onAfterMove(x1, y1, x2, y2, org) { if (x1 !== x2 || y1 !== y2) { - this.positions[Helper.posId(x1, y1)] = undefined; - this.positions[Helper.posId(x2, y2)] = org; + this.positions[POSID(x1, y1)] = undefined; + this.positions[POSID(x2, y2)] = org; } return true; @@ -128,7 +137,7 @@ class Organisms extends BaseOrganisms { _onGetEnergy(org, x, y, ret) { if (x < 0 || y < 0 || !Number.isInteger(x) || !Number.isInteger(y)) {return} - const posId = Helper.posId(x, y); + const posId = POSID(x, y); if (typeof(this.positions[posId]) === 'undefined') { ret.ret = this.world.getDot(x, y) @@ -139,26 +148,27 @@ class Organisms extends BaseOrganisms { _onEat(org, x, y, ret) { const positions = this.positions; - const eat = ret.ret; + // + // Amount of eat energy depends on organism size. Small organisms + // eat less, big - more + // + const eat = ret.ret / (OConfig.codeMaxSize / (org.vm.size || 1)); let dir; - [x, y, dir] = Helper.normalize(x, y); + [x, y, dir] = NORMALIZE(x, y); - const posId = Helper.posId(x, y); + const posId = POSID(x, y); if (typeof(positions[posId]) === 'undefined') { - if (eat < 0) { - if (this.world.isFree(x, y)) { - this.parent.fire(EVENTS.EAT_ENERGY, eat); - this.world.setDot(x, y, -eat); - } - } else { + if (eat > 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); + } else { + ret.ret = 0; } } else { const victimOrg = positions[posId]; ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); - victimOrg.energy <= eat && this.parent.fire(EVENTS.KILL_EAT, victimOrg); + victimOrg.energy <= ret.ret && this.parent.fire(EVENTS.KILL_EAT, victimOrg); victimOrg.grabEnergy(ret.ret); } } @@ -168,7 +178,7 @@ class Organisms extends BaseOrganisms { const man = this.parent; let dir; - [x2, y2, dir] = Helper.normalize(x2, y2); + [x2, y2, dir] = NORMALIZE(x2, y2); // // Organism has moved, but still is within the current world (client) // @@ -238,11 +248,15 @@ class Organisms extends BaseOrganisms { } _onCheckAt(x, y, ret) { - const org = this.positions[Helper.posId(x, y)]; - let dir; + const org = this.positions[POSID(x, y)]; - [x, y, dir] = Helper.normalize(x, y); - ret.ret = typeof(org) === 'undefined' ? this.world.getDot(x, y) : org.energy; + if (typeof(org) === 'undefined') { + let dir; + [x, y, dir] = NORMALIZE(x, y); + ret.ret = this.world.getDot(x, y); + } else { + ret.ret = org.energy; + } } } diff --git a/client/src/manager/plugins/organisms/garmin/Operators.js b/client/src/manager/plugins/organisms/garmin/Operators.js index 03d3bba..99ce939 100644 --- a/client/src/manager/plugins/organisms/garmin/Operators.js +++ b/client/src/manager/plugins/organisms/garmin/Operators.js @@ -25,8 +25,8 @@ const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; class OperatorsGarmin extends Operators { - constructor(offs, vars, obs) { - super(offs, vars, obs); + constructor(offs, vars, callbacks) { + super(offs, vars, callbacks); /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -65,7 +65,7 @@ class OperatorsGarmin extends Operators { this._OPERATORS_CB = null; this._CONDITIONS = null; this._OPERATORS = null; - this._TRIGS = null; + //this._TRIGS = null; super.destroy(); } diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index deab6a7..7070a63 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -20,10 +20,11 @@ class OrganismGarmin extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located + * @param {Object} callbacks Map of callback functions * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, parent = null) { - super(id, x, y, alive, item, Operators, parent); + constructor(id, x, y, alive, item, callbacks, parent = null) { + super(id, x, y, alive, item, Operators, callbacks, parent); this._needRun = true; @@ -35,7 +36,7 @@ class OrganismGarmin extends Organism { } onRun() { - if (Fitness.run(this)) {this.fire(EVENTS.STOP, this)} + if (Fitness.run(this)) {this.callbacks[EVENTS.STOP](this)} this._needRun = false; } diff --git a/client/src/manager/plugins/organisms/garmin/Organisms.js b/client/src/manager/plugins/organisms/garmin/Organisms.js index a484bd4..8a584f1 100644 --- a/client/src/manager/plugins/organisms/garmin/Organisms.js +++ b/client/src/manager/plugins/organisms/garmin/Organisms.js @@ -20,6 +20,8 @@ class Organisms extends BaseOrganisms { super(manager); this._maxChanges = 0; this._maxEnergy = 0; + + this.callbacks[EVENTS.STOP] = this._onStop.bind(this); } /** @@ -45,11 +47,6 @@ class Organisms extends BaseOrganisms { if (org.changes > this._maxChanges) {this._maxChanges = org.changes} } - addOrgHandlers(org) { - super.addOrgHandlers(org); - org.on(EVENTS.STOP, this._onStop.bind(this)); - } - reset() { super.reset(); this._maxChanges = 0; diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index a83d5c8..665ff44 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -162,7 +162,7 @@ class Status extends Configurable { status.lps = fix((this.parent.codeRuns - this._codeRuns) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); - status.penergy = fix(this._pickEnergy * 10, 2); + status.penergy = fix(this._pickEnergy * 1000, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); status.changes = +(this._changes).toFixed(1); status.fit = fix(this._fitness / 100, 2); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 5065321..1840180 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -45,11 +45,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 5760, + worldWidth: 1920, /** * {Number} World height */ - worldHeight: 3240, + worldHeight: 1080, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -58,7 +58,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: true, + worldCyclical: false, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -68,7 +68,7 @@ ClientConfig.init({ * {Number} Amount of energy in every block. See worldEnergyDots * config for details. */ - worldEnergyInDot: 0xAAFF00, + worldEnergyInDot: 0x00ddff, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less @@ -76,13 +76,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.3, + worldEnergyCheckPercent: 0.1, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 200, + worldEnergyCheckPeriod: 1000, /** * {Boolean} Turns on/off scroll bars in a 2D canvas */ @@ -90,7 +90,7 @@ ClientConfig.init({ /** * {Number} Zoom speed 0..1 */ - worldZoomSpeed: 0.05, + worldZoomSpeed: 0.1, /** * {Number} Mode for showing/suppressing of messages. Possible values: * 0 - all messages diff --git a/client/src/vm/Operators.js b/client/src/vm/Operators.js index 1e09374..24e67fa 100644 --- a/client/src/vm/Operators.js +++ b/client/src/vm/Operators.js @@ -5,26 +5,26 @@ * @author flatline */ class Operators { - constructor(offs, vars, obs) { + constructor(offs, vars, callbacks) { /** * {Array} Array of offsets for closing braces. For 'for', 'if' * and other operators. */ - this.offs = offs; + this.offs = offs; /** * {Array} Available variables */ - this.vars = vars; + this.vars = vars; /** - * {Observer} Observer for sending events outside + * {Observer} Callbacks map for calling outside callbacks */ - this.obs = obs; + this.callbacks = callbacks; } destroy() { - this.offs = null; - this.vars = null; - this.obs = null; + this.offs = null; + this.vars = null; + this.callbacks = null; } /** diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 86b5479..18cf9ab 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -27,14 +27,14 @@ class VM extends Observer { /** * Creates VM instance. parent is used if VM instance is in a * cloning mode and we have to create a copy of it. - * @param {Observer} obs Observer instance for Operators class + * @param {Object} callbacks Callbacks map for calling outside methods * @param {Function} operatorCls Class of operators * @param {VM} parent Parent VM instance in case of cloning */ - constructor(obs, operatorCls, parent = null) { + constructor(callbacks, operatorCls, parent = null) { super(EVENT_AMOUNT); - this._obs = obs; + this._callbacks = callbacks; /** * {Function} Class of operators, with implementation of all available * script parts for current VM instance @@ -50,7 +50,7 @@ class VM extends Observer { /** * {Function} Class, which implement all supported operators */ - this._operators = new operatorCls(this._offsets, this._vars, obs); + this._operators = new operatorCls(this._offsets, this._vars, callbacks); this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; this._line = 0; @@ -78,7 +78,7 @@ class VM extends Observer { this._vars = json.vars; this._code = json.code; this._line = json.line; - this._operators = new this._operatorCls(this._offsets, this._vars, this._obs); + this._operators = new this._operatorCls(this._offsets, this._vars, this._callbacks); } /** @@ -91,6 +91,7 @@ class VM extends Observer { run(org) { const code = this._code; const lines = code.length; + if (lines < 1) {return 0} const ops = this._ops; const offs = this._offsets; const period = OConfig.codeYieldPeriod; @@ -131,7 +132,7 @@ class VM extends Observer { this._offsets = null; this._vars = null; this._code = null; - this._obs = null; + this._callbacks = null; this._ops = null; super.destroy(); From 2f4168ffea260e75aa4d80be979fb0d39c87428d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Feb 2018 14:55:35 +0200 Subject: [PATCH 158/291] removed orgCloneEnergyPercent Config fixed an issue of grabbing energy from died organism --- .../src/manager/plugins/organisms/Config.js | 19 +++++++------------ .../src/manager/plugins/organisms/Organism.js | 10 ++-------- .../plugins/organisms/dos/Operators.js | 4 ++-- .../plugins/organisms/dos/OrganismSpec.js | 3 --- .../plugins/organisms/dos/Organisms.js | 7 ++++--- 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 47e63e6..de120b9 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -47,11 +47,6 @@ const Config = { * mutations probabilities. Otherwise these probabilities will be constant */ orgMutationPerOrg: false, - /** - * {Number} Percent of energy, which will be given to the child. Set to 0.0 - * to share the same amount of energy with child (energy duplication) - */ - orgCloneEnergyPercent: 0.5, /** * {Number} Minimum energy for one organism, which will be multiplied on * organism code size. This value permits organism to have a baby (clone). @@ -64,7 +59,7 @@ const Config = { * organism has cloned. If population is less then orgMaxOrgs, then no killing * will be provided. Killing of organism will be done using tournament approach */ - orgKillOnClone: false, + orgKillOnClone: true, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -75,7 +70,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 10000, + orgRainMutationPeriod: 12000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -91,12 +86,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 10000, + orgCrossoverPeriod: 15000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 10000, + orgRandomOrgPeriod: 15000, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -132,11 +127,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 2000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 1000, + orgStartAmount: 2000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -147,7 +142,7 @@ const Config = { * {Number} Begin color of "empty". It's just an index of color. Starts from * 0 and till Number.MAX_VALUE */ - orgStartColor: 24, + orgStartColor: 50, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index a1167cb..9bc8f2f 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -105,7 +105,6 @@ class Organism extends Observer { get mutationProbs() {return this._mutationProbs} get mutationPeriod() {return this._mutationPeriod} get mutationPercent() {return this._mutationPercent} - get cloneEnergyPercent() {return this._cloneEnergyPercent} get energy() {return this._energy} get startEnergy() {return this._startEnergy} get color() {return this._color} @@ -116,7 +115,6 @@ class Organism extends Observer { set x(newX) {this._x = newX} set y(newY) {this._y = newY} - set cloneEnergyPercent(p) {this._cloneEnergyPercent = p} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} set energy(e) {this._energy = e} @@ -168,7 +166,6 @@ class Organism extends Observer { color : this._color, colorIndex : this._colorIndex, mutationProbs : this._mutationProbs, - cloneEnergyPercent : this._cloneEnergyPercent, mutationPeriod : this._mutationPeriod, mutationPercent : this._mutationPercent, mem : this.mem.slice() @@ -200,16 +197,15 @@ class Organism extends Observer { this._color = json.color; this._colorIndex = json.colorIndex; this._mutationProbs = json.mutationProbs; - this._cloneEnergyPercent = json.cloneEnergyPercent; this._mutationPeriod = json.mutationPeriod; this._mutationPercent = json.mutationPercent; this._mem = json.mem.slice(); } grabEnergy(amount) { - if (!IS_NUM(amount) || amount === 0) {return true} + if (!this._alive || !IS_NUM(amount) || amount === 0) {return true} const noEnergy = (this._energy -= amount) < 1; - this._callbacks && this._callbacks[GRAB_ENERGY](amount + (noEnergy ? -this._energy : 0)); + this._callbacks[GRAB_ENERGY](amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); return !noEnergy; } @@ -248,7 +244,6 @@ class Organism extends Observer { this._colorIndex = OConfig.orgStartColor * MAX_BITS; this._color = Organism._getColor(this._colorIndex); this._mutationProbs = OConfig.orgMutationProbs.slice(); - this._cloneEnergyPercent = OConfig.orgCloneEnergyPercent; this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; this._mem = new Array(Math.pow(2, OConfig.orgMemBits)); @@ -263,7 +258,6 @@ class Organism extends Observer { this._color = parent.color; this._colorIndex = parent.colorIndex; this._mutationProbs = parent.mutationProbs.slice(); - this._cloneEnergyPercent = parent.cloneEnergyPercent; this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; this._mem = parent.mem.slice(); diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 8346f21..7abbe07 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -249,10 +249,10 @@ class OperatorsDos extends Operators { _eat(org, num, x, y) { const amount = this.vars[VAR1(num)]; - if (!IS_NUM(amount) || amount === 0) {return 0} + if (!IS_NUM(amount) || amount <= 0) {return 0} const ret = this._ret; - if ((ret.ret = amount) <= 0) {return 0} + ret.ret = amount; this.callbacks[EVENTS.EAT](org, x, y, ret); org.energy += ret.ret; diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index cad5269..f066a40 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -23,7 +23,6 @@ describe("client/src/organism/OrganismDos", () => { expect(org.energy === OConfig.orgStartEnergy).toEqual(true); expect(org.color === OConfig.orgStartColor).toEqual(true); expect(org.mem.length === 0).toEqual(true); - expect(org.cloneEnergyPercent === OConfig.orgCloneEnergyPercent).toEqual(true); expect(org.iterations === 0).toEqual(true); org.destroy(); @@ -38,7 +37,6 @@ describe("client/src/organism/OrganismDos", () => { parent.cloneMutationPercent = 0.1; parent.mutationPeriod = 145; parent.mutationPercent = 0.2; - parent.cloneEnergyPercent = 0.34; parent._mem = [1,2,4,3]; let org = new OrganismDos(0, 1, 2, true, null, () => {}, parent); @@ -51,7 +49,6 @@ describe("client/src/organism/OrganismDos", () => { expect(org.cloneMutationPercent === parent.cloneMutationPercent).toEqual(true); expect(org.mutationPeriod === parent.mutationPeriod).toEqual(true); expect(org.mutationPercent === parent.mutationPercent).toEqual(true); - expect(org.cloneEnergyPercent === parent.cloneEnergyPercent).toEqual(true); expect(eq(org.mem, parent.mem)).toEqual(true); expect(org.changes === 1).toEqual(true); expect(org.iterations === 0).toEqual(true); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 847663d..0d5c33f 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -75,11 +75,12 @@ class Organisms extends BaseOrganisms { * @override */ onClone(org, child) { - const percent = org.cloneEnergyPercent; - if (percent === 0.0) {return} const orgEnergy = org.energy; const childEnergy = child.energy; - let energy = (((orgEnergy * percent) + 0.5) << 1) >>> 1; // analog of Math.round() + // + // Clone percent is always 0.5 + // + let energy = (((orgEnergy * 0.5) + 0.5) << 1) >>> 1; // analog of Math.round() // // This is very special/rare case, when organisms cheating by creating // ancestors and put all energy into them at the same time resetting From 1e04608810ac632d8e95d33dc9979e6034ca6250 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 2 Feb 2018 23:53:48 +0200 Subject: [PATCH 159/291] removed google-charts dependency. implemented by hands #83 added dos/Operators.onConst() as a speed optimization --- .../plugins/organisms/dos/Code2String.js | 49 ++++++++++--------- .../plugins/organisms/dos/Operators.js | 14 ++++-- .../manager/plugins/status/charts/Chart.js | 36 ++++++++++++-- client/src/vm/VM.js | 16 +++--- package.json | 1 - 5 files changed, 76 insertions(+), 40 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 9bbce53..3b63b10 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -31,30 +31,31 @@ class Code2String { */ this._OPERATORS_CB = { 0 : this._onVar.bind(this), + 1 : this._onConst.bind(this), //1: this._onFunc.bind(this), - 1 : this._onCondition.bind(this), - 2 : this._onLoop.bind(this), - 3 : this._onOperator.bind(this), + 2 : this._onCondition.bind(this), + 3 : this._onLoop.bind(this), + 4 : this._onOperator.bind(this), //4 : this._onNot.bind(this), //5 : this._onPi.bind(this), //6 : this._onTrig.bind(this), - 4 : this._onLookAt.bind(this), - 5 : this._onEatLeft.bind(this), - 6 : this._onEatRight.bind(this), - 7 : this._onEatUp.bind(this), - 8 : this._onEatDown.bind(this), - 9 : this._onStepLeft.bind(this), - 10: this._onStepRight.bind(this), - 11: this._onStepUp.bind(this), - 12: this._onStepDown.bind(this), - 13: this._onFromMem.bind(this), - 14: this._onToMem.bind(this), - 15: this._onMyX.bind(this), - 16: this._onMyY.bind(this), - 17: this._onCheckLeft.bind(this), - 18: this._onCheckRight.bind(this), - 19: this._onCheckUp.bind(this), - 20: this._onCheckDown.bind(this) + 5 : this._onLookAt.bind(this), + 6 : this._onEatLeft.bind(this), + 7 : this._onEatRight.bind(this), + 8 : this._onEatUp.bind(this), + 9 : this._onEatDown.bind(this), + 10: this._onStepLeft.bind(this), + 11: this._onStepRight.bind(this), + 12: this._onStepUp.bind(this), + 13: this._onStepDown.bind(this), + 14: this._onFromMem.bind(this), + 15: this._onToMem.bind(this), + 16: this._onMyX.bind(this), + 17: this._onMyY.bind(this), + 18: this._onCheckLeft.bind(this), + 19: this._onCheckRight.bind(this), + 20: this._onCheckUp.bind(this), + 21: this._onCheckDown.bind(this) }; this._OPERATORS_CB_LEN = Object.keys(this._OPERATORS_CB).length; /** @@ -139,11 +140,13 @@ class Code2String { * @return {String} Parsed vm line string */ _onVar(num) { - const var1 = VAR1(num); - const isConst = VAR2(num) >= HALF_OF_VAR; + return `v${VAR0(num)}=${'v' + VAR1(num)}`; + } - return `v${VAR0(num)}=${isConst ? Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : ('v' + var1)}`; + _onConst(num) { + return `v${VAR0(num)}=${Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER)}`; } + // // _onFunc(num) { // return ''; diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 7abbe07..fc5cd89 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -29,7 +29,6 @@ const BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; const FOUR_BITS = 4; const BITS_FOR_NUMBER = 16; const IS_NUM = Helper.isNumeric; -const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; const BITS = Num.getBits; @@ -52,6 +51,7 @@ class OperatorsDos extends Operators { */ this._OPERATORS_CB = [ this.onVar.bind(this), + this.onConst.bind(this), //this.onFunc.bind(this), this.onCondition.bind(this), this.onLoop.bind(this), @@ -107,7 +107,13 @@ class OperatorsDos extends Operators { * @return {Number} Parsed vm line string */ onVar(num, line, org) { - this.vars[VAR0(num)] = VAR2(num) < HALF_OF_VAR ? BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER) : this.vars[VAR1(num)]; + this.vars[VAR0(num)] = this.vars[VAR1(num)]; + org.grabEnergy(OConfig.orgOperatorWeights[0]); + return ++line; + } + + onConst(num, line, org) { + this.vars[VAR0(num)] = BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER); org.grabEnergy(OConfig.orgOperatorWeights[0]); return ++line; } @@ -273,7 +279,7 @@ class OperatorsDos extends Operators { } /** - * Returns offset for closing bracket of blocked operators like + * Returns offset for closing bracket of block operators like * "if", "for" and so on. These operators shouldn't overlap each * other. for example: * @@ -292,7 +298,7 @@ class OperatorsDos extends Operators { * @returns {Number} */ _getOffs(line, lines, offs) { - let offset = line + offs < lines ? line + offs + 1 : lines; + const offset = line + offs < lines ? line + offs + 1 : lines; const offsets = this.offs; const length = offsets.length; diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index 60715e1..261a582 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -7,11 +7,12 @@ * * @author flatline */ -const GoogleCharts = require('google-charts').GoogleCharts; const _get = require('lodash/get'); const Helper = require('./../../../../../../common/src/Helper'); const Config = require('./Config'); +const GOOGLE_CHARTS_URL = 'https://www.gstatic.com/charts/loader.js'; + class Chart { constructor(title, cfg) { this._options = { @@ -27,7 +28,7 @@ class Chart { this._el = null; this._cfg = cfg; - GoogleCharts.load(cfg.active ? this._onReady.bind(this) : () => {}, 'corechart'); + this._loadLib(this._onReady.bind(this)); } /** @@ -67,6 +68,33 @@ class Chart { this._options = null; } + _loadLib(cb) { + let scriptEl; + const googleLib = window.google; + const setReadyCb = () => { + window.google.charts.load('current', {'packages': ['corechart']}); + window.google.charts.setOnLoadCallback(() => this._cfg.active && cb()); + }; + // + // Google charts library has already loaded + // + if (googleLib) {return setReadyCb()} + // + // Google charts library is loading now + // + if (scriptEl = document.querySelector(`script[src="${GOOGLE_CHARTS_URL}"]`)) { + return scriptEl.addEventListener('load', setReadyCb); + } + // + // Google charts library hasn't loaded yet + // + scriptEl = document.createElement('SCRIPT'); + scriptEl.type = 'text/javascript'; + scriptEl.src = GOOGLE_CHARTS_URL; + scriptEl.onload = setReadyCb; + document.head.appendChild(scriptEl); + } + _onReady() { document.body.appendChild(this._el = Helper.setStyles('DIV', { position: 'absolute', @@ -75,7 +103,7 @@ class Chart { this._updatePos(this._cfg.pos); this._ready = true; - this._chart = new google.visualization.LineChart(this._el); + this._chart = new window.google.visualization.LineChart(this._el); !this._data && (this._data = this._createDataTable()); } @@ -154,7 +182,7 @@ class Chart { } _createDataTable() { - const data = new google.visualization.DataTable(); + const data = new window.google.visualization.DataTable(); data.addColumn('string', 'horizontal'); data.addColumn('number', 'vertical'); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 18cf9ab..c59f9ea 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -34,26 +34,26 @@ class VM extends Observer { constructor(callbacks, operatorCls, parent = null) { super(EVENT_AMOUNT); - this._callbacks = callbacks; + this._callbacks = callbacks; /** * {Function} Class of operators, with implementation of all available * script parts for current VM instance */ - this._operatorCls = operatorCls; + this._operatorCls = operatorCls; /** * {Array} Array of two numbers. first - line number where we have * to return if first line appears. second - line number, where ends * closing block '}' of block operator (e.g. for, if,...). */ - this._offsets = []; - this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); + this._offsets = []; + this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); /** * {Function} Class, which implement all supported operators */ - this._operators = new operatorCls(this._offsets, this._vars, callbacks); - this._ops = this._operators.operators; - this._code = parent && parent.code.slice() || []; - this._line = 0; + this._operators = new operatorCls(this._offsets, this._vars, callbacks); + this._ops = this._operators.operators; + this._code = parent && parent.code.slice() || []; + this._line = 0; } get code() {return this._code} diff --git a/package.json b/package.json index ea56373..d57ef03 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "dependencies": { "babel-cli": "^6.24.1", "babel-preset-env": "^1.6.0", - "google-charts": "^1.0.0", "jasmine": "^2.6.0", "js-beautify": "^1.6.14", "panzoom": "^4.1.0", From e7f8aff3c138f1411d1a4e4bbb30863e44eccc3f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Feb 2018 01:47:57 +0200 Subject: [PATCH 160/291] in process of fixing tests #83 removed modeNodeJs fixed small syntax error disabled Charts plugin for NodeJs mode added an ability to skip empty plugin configurations --- client/src/manager/Manager.js | 4 +- client/src/manager/ManagerSpec.js | 60 ++++++++----------- client/src/manager/plugins/client/Client.js | 2 +- .../src/manager/plugins/client/ClientSpec.js | 7 --- .../plugins/organisms/dos/OperatorsSpec.js | 10 +++- client/src/manager/plugins/status/Status.js | 2 +- client/src/share/Config.js | 14 +++-- common/src/plugins/Plugins.js | 1 + common/src/plugins/Request.js | 2 +- server/src/App.js | 4 -- server/src/server/ServerSpec.js | 3 - server/src/server/plugins/ApiSpec.js | 4 -- 12 files changed, 46 insertions(+), 67 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 7a35fb4..bc6c888 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -92,7 +92,7 @@ class Manager extends Observer { plugins : Config.plugIncluded, async : true, run : this._onDone.bind(this), - isBrowser: !Config.modeNodeJs + isBrowser: !Config.MODE_NODE_JS }); } @@ -217,7 +217,7 @@ class Manager extends Observer { (() => { let callback; - if (Config.modeNodeJs) { + if (Config.MODE_NODE_JS) { this.zeroTimeout = (fn) => setTimeout(callback = fn); return; } diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index f4e55ac..b078e2f 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -3,8 +3,6 @@ describe("client/src/manager/Manager", () => { const Config = require('./../../../client/src/share/Config').Config; const OConfig = require('./../manager/plugins/organisms/Config'); const SConfig = require('./../../../server/src/share/Config').Config; - const OLD_MODE = Config.modeNodeJs; - Config.modeNodeJs = true; const Server = require('./../../../server/src/server/Server').Server; const EVENTS = require('./../../../client/src/share/Events').EVENTS; const SEVENTS = require('./../../../server/src/server/Server').EVENTS; @@ -33,17 +31,21 @@ describe("client/src/manager/Manager", () => { let dist; let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; - - beforeEach(() => { + function deletePluginConfigs() { delete Config.ips; delete Config.organisms; delete Config.status; + delete Config.charts; + delete Config.console; + } + + beforeEach(() => { + deletePluginConfigs(); }); beforeAll(() => { jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; Config.serverHost = SERVER_HOST; Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); - Config.modeNodeJs = true; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; SConfig.port = Config.serverPort; @@ -73,7 +75,6 @@ describe("client/src/manager/Manager", () => { Console.error = error; Console.warn = warn; Console.info = info; - Config.modeNodeJs = OLD_MODE; Config.plugIncluded.push('ips/Ips'); jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; Config.serverHost = host; @@ -104,8 +105,7 @@ describe("client/src/manager/Manager", () => { }); it("Checking creation of two managers", (done) => { const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man2 = new Manager(false); waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { @@ -122,7 +122,7 @@ describe("client/src/manager/Manager", () => { Config.worldWidth = 10; Config.worldHeight = 10; - for (let i = 0; i < amount; i++) {delete Config.organisms;delete Config.status; mans.push(new Manager(false))} + for (let i = 0; i < amount; i++) {deletePluginConfigs(); mans.push(new Manager(false))} for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} if (waitObj.done) { @@ -258,8 +258,7 @@ describe("client/src/manager/Manager", () => { const max = OConfig.orgMaxOrgs; const server = new Server(); const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man2 = new Manager(false); let iterated1 = false; let iterated2 = false; @@ -331,8 +330,7 @@ describe("client/src/manager/Manager", () => { Config.worldWidth = 400; Config.worldHeight = 400; const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man2 = new Manager(false); let iterated1 = 0; let iterated2 = 0; @@ -370,7 +368,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() } else if (man2.organisms.size === 2) { destroy(); } @@ -399,8 +397,7 @@ describe("client/src/manager/Manager", () => { Config.worldHeight = 400; Config.worldWidth = 400; const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man2 = new Manager(false); let iterated1 = 0; let iterated2 = 0; @@ -440,7 +437,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() man1.on(EVENTS.STEP_OUT, () => { expect(doneInc < 3).toBe(true); ++doneInc; @@ -487,8 +484,7 @@ describe("client/src/manager/Manager", () => { waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { for (let i = 0; i < CLIENTS; i++) { - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); mans.push(man = new Manager(false)); man.run(() => ++amount === CLIENTS && (waitObj.done = true)); } @@ -526,8 +522,7 @@ describe("client/src/manager/Manager", () => { Config.worldHeight = 100; SConfig.maxConnections = CLIENTS; man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); man2 = new Manager(false); testQ(done, @@ -586,8 +581,7 @@ describe("client/src/manager/Manager", () => { Config.worldHeight = 10; SConfig.maxConnections = CLIENTS; man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); man2 = new Manager(false); waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { @@ -640,8 +634,7 @@ describe("client/src/manager/Manager", () => { cfg.set('serverPort', 3000); cfg.set('serverHost', SERVER_HOST); const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); cfg.set('serverPort', 3001); const man2 = new Manager(false); ocfg.set('orgStartAmount', 1); @@ -657,7 +650,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() } else if (man2.organisms.size === 2) { destroy(); } @@ -719,8 +712,7 @@ describe("client/src/manager/Manager", () => { cfg.set('serverPort', 3000); cfg.set('serverHost', SERVER_HOST); const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); cfg.set('serverPort', 3001); const man2 = new Manager(false); ocfg.set('orgStartAmount', 1); @@ -736,7 +728,7 @@ describe("client/src/manager/Manager", () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() man1.on(EVENTS.KILL, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); man2.on(EVENTS.STEP_IN, () => stepInFlag = true); @@ -811,7 +803,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && org1 === null) { org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001010000000000000000000000000); // onStepRight() + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() man1.on(EVENTS.KILL, () => destroyFlag = true); man1.on(EVENTS.STEP_IN, () => stepInBack = true); } else if (destroyFlag && stepInBack) { @@ -835,11 +827,9 @@ describe("client/src/manager/Manager", () => { cfg.set('worldWidth', 10); cfg.set('worldHeight', 10); const man1 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man2 = new Manager(false); - delete Config.organisms; - delete Config.status; + deletePluginConfigs(); const man3 = new Manager(false); let freePos = World.prototype.getFreePos; let waitObj = {done: false}; @@ -870,7 +860,7 @@ describe("client/src/manager/Manager", () => { testQ(done, [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], [waitObj], - [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001010000000000000000000000000)], // onStepRight() + [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001011000000000000000000000000)], // onStepRight() [man3, EVENTS.STEP_IN, () => {}, () => destroy()] ); }); diff --git a/client/src/manager/plugins/client/Client.js b/client/src/manager/plugins/client/Client.js index b053ec3..3ad4baf 100644 --- a/client/src/manager/plugins/client/Client.js +++ b/client/src/manager/plugins/client/Client.js @@ -29,7 +29,7 @@ const CLIENT_EVENTS = Object.assign({ class Client extends BaseClient { constructor(manager) { - super(Config.serverHost, Config.serverPort, Config.modeNodeJs, CLIENT_EVENTS); + super(Config.serverHost, Config.serverPort, Config.MODE_NODE_JS, CLIENT_EVENTS); this.EVENTS = CLIENT_EVENTS; this._manager = manager; this._onStepOutCb = this._onStepOut.bind(this); diff --git a/client/src/manager/plugins/client/ClientSpec.js b/client/src/manager/plugins/client/ClientSpec.js index 0bb9074..1ee6171 100644 --- a/client/src/manager/plugins/client/ClientSpec.js +++ b/client/src/manager/plugins/client/ClientSpec.js @@ -14,7 +14,6 @@ describe("client/src/manager/plugins/Client", () => { const host = Config.serverHost; const port = SConfig.port; const maxConns = SConfig.maxConnections; - let isNodeJs; let Client; let CEVENTS; let Server; @@ -28,11 +27,6 @@ describe("client/src/manager/plugins/Client", () => { let dist; beforeAll(() => { - // - // These two lines set modeNodeJs mode to Node.js as running environment - // - isNodeJs = Config.modeNodeJs; - Config.modeNodeJs = true; Config.serverHost = 'ws://127.0.0.1'; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; @@ -59,7 +53,6 @@ describe("client/src/manager/plugins/Client", () => { SConsole.info = () => {}; }); afterAll(() => { - api.set('modeNodeJs', isNodeJs); SConsole.error = serror; SConsole.warn = swarn; SConsole.info = sinfo; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index dff8a13..2cff8ee 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -6,6 +6,8 @@ describe("client/src/organism/OperatorsDos", () => { let EVENT_AMOUNT = require('./../../../../share/Events').EVENT_AMOUNT; let Config = require('./../../../../share/Config').Config; let OConfig = require('./../../organisms/Config'); + let OrganismDos = require('./../../organisms/dos/Organism'); + let OEvents = require('./../../organisms/Organism').EVENTS; let api = require('./../../../../share/Config').api; let cbpv = null; @@ -14,23 +16,25 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking onVar() method", () => { let ops = new OperatorsDos([], [0, 0, 0, 0], new Observer()); + let org = new OrganismDos(0, 0, 0, true, {}, {[OEvents.GRAB_ENERGY]: ()=>{}}); - expect(ops.onVar(0x00ffffff, 0)).toEqual(1); + expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 0).toEqual(true); expect(ops.vars[2] === 0).toEqual(true); expect(ops.vars[3] === 0).toEqual(true); - expect(ops.onVar(0x000fffff, 0)).toEqual(1); + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); expect(ops.vars[0] === 0).toEqual(true); expect(ops.vars[1] === 0).toEqual(true); expect(ops.vars[2] === 0).toEqual(true); expect(ops.vars[3] === 0).toEqual(true); - expect(ops.onVar(0x0000ffff, 0)).toEqual(1); + expect(ops.onVar(0x0000ffff, 0, org)).toEqual(1); expect(ops.vars[0] === 0x3fff).toEqual(true); expect(ops.vars[1] === 0).toEqual(true); expect(ops.vars[2] === 0).toEqual(true); expect(ops.vars[3] === 0).toEqual(true); + org.destroy(); ops.destroy(); }); diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 665ff44..ebae981 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -100,7 +100,7 @@ class Status extends Configurable { man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); man.off(EVENTS.IPS, this._onIpsCb); - Helper.unoverride(manager, 'onLoop', this._onLoopCb); + Helper.unoverride(man, 'onLoop', this._onLoopCb); this._onKillOrgCb = null; this._onKillTourCb = null; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 1840180..00f2f4a 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -11,6 +11,8 @@ const QUIET_ALL = 0; const QUIET_IMPORTANT = 1; const QUIET_NO = 2; +const IS_NODE_JS = typeof window === 'undefined'; + class ClientConfig extends Config {} ClientConfig.init({ @@ -22,6 +24,11 @@ ClientConfig.init({ QUIET_ALL, QUIET_IMPORTANT, QUIET_NO, + /** + * {Boolean} Running mode. It's also possible to run construct only on + * server side without browser. For this it should be set to true. + */ + MODE_NODE_JS: IS_NODE_JS, /** * {Array} Array of paths to Manager's plugins. Root folder for plugins * should be './client/src/manager/plugins/'. @@ -33,7 +40,7 @@ ClientConfig.init({ 'client/Client', 'Energy', 'status/console/Console', - 'status/charts/Charts', + IS_NODE_JS ? '' : 'status/charts/Charts', 'ips/Ips', 'backup/Backup' ], @@ -98,11 +105,6 @@ ClientConfig.init({ * 2 - no messages */ modeQuiet: QUIET_IMPORTANT, - /** - * {Boolean} Running mode. It's also possible to run construct only on - * server side without browser. For this it should be set to true. - */ - modeNodeJs: false, /** * {Number} Port number for connecting with server */ diff --git a/common/src/plugins/Plugins.js b/common/src/plugins/Plugins.js index 7a1f5c1..45bb4e0 100644 --- a/common/src/plugins/Plugins.js +++ b/common/src/plugins/Plugins.js @@ -88,6 +88,7 @@ class Plugins { for (let p of cfg.plugins) { const path = p.path || p; + if (!path) {continue} const name = path.split('/').slice(-1)[0]; let pluginCls = this.require(path); diff --git a/common/src/plugins/Request.js b/common/src/plugins/Request.js index a39a6cc..949aabb 100644 --- a/common/src/plugins/Request.js +++ b/common/src/plugins/Request.js @@ -9,7 +9,7 @@ const WebSocket = require('ws'); const Helper = require('./../Helper'); const Config = require('./../../../client/src/share/Config').Config; const MASKS = require('./../net/Requests').MASKS; -const Console = require(`./../../../${Config.modeNodeJs ? 'server' : 'client'}/src/share/Console`); +const Console = require(`./../../../${Config.MODE_NODE_JS ? 'server' : 'client'}/src/share/Console`); class Request { /** diff --git a/server/src/App.js b/server/src/App.js index 4f763ae..fb6ebe9 100644 --- a/server/src/App.js +++ b/server/src/App.js @@ -6,9 +6,5 @@ */ const Server = require('./server/Server').Server; const Config = require('./share/Config').Config; -// -// Server always run under Node.js -// -Config.modeNodeJs = true; const server = new Server(Config.port); server.run(); \ No newline at end of file diff --git a/server/src/server/ServerSpec.js b/server/src/server/ServerSpec.js index e7b73c6..c4df35a 100644 --- a/server/src/server/ServerSpec.js +++ b/server/src/server/ServerSpec.js @@ -4,8 +4,6 @@ describe("server/src/server/Server", () => { const SConfig = require('./../../../server/src/share/Config').Config; const Observer = require('./../../../common/src/Observer'); const Server = require('./Server').Server; - const OLD_MODE = Config.modeNodeJs; - Config.modeNodeJs = true; const Client = require('./../../../client/src/manager/plugins/client/Client').Client; const SEVENTS = require('./Server').EVENTS; const CEVENTS = require('./../../../client/src/manager/plugins/client/Client').EVENTS; @@ -54,7 +52,6 @@ describe("server/src/server/Server", () => { Console.error = error; Console.warn = warn; Console.info = info; - Config.modeNodeJs = OLD_MODE; Config.serverHost = host; SConfig.modeDistributed = dist; SConfig.port = port; diff --git a/server/src/server/plugins/ApiSpec.js b/server/src/server/plugins/ApiSpec.js index 93b848b..257cb9e 100644 --- a/server/src/server/plugins/ApiSpec.js +++ b/server/src/server/plugins/ApiSpec.js @@ -4,8 +4,6 @@ describe("server/src/server/plugins/Api", () => { const Observer = require('./../../../../common/src/Observer'); const Server = require('./../Server').Server; const SEVENTS = require('./../Server').EVENTS; - const OLD_MODE = Config.modeNodeJs; - Config.modeNodeJs = true; const Client = require('./../../../../client/src/manager/plugins/client/Client').Client; const CEVENTS = require('./../../../../client/src/manager/plugins/client/Client').EVENTS; const EVENT_AMOUNT = require('./../../../../client/src/share/Events').EVENT_AMOUNT; @@ -26,7 +24,6 @@ describe("server/src/server/plugins/Api", () => { beforeAll(() => { Config.serverHost = 'ws://127.0.0.1'; - Config.modeNodeJs = true; dist = SConfig.modeDistributed; SConfig.modeDistributed = false; SConfig.port = Config.serverPort; @@ -52,7 +49,6 @@ describe("server/src/server/plugins/Api", () => { Console.error = error; Console.warn = warn; Console.info = info; - Config.modeNodeJs = OLD_MODE; Config.serverHost = host; SConfig.modeDistributed = dist; SConfig.port = port; From 8cf59f5304bf993f54b2d1f1954c46feb66980dc Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Feb 2018 12:31:09 +0200 Subject: [PATCH 161/291] new default config many small refactoring removed iq parameter (this is the same like eenergy) --- .../src/manager/plugins/organisms/Config.js | 11 ++-- .../manager/plugins/organisms/Organisms.js | 9 ++-- .../plugins/organisms/garmin/Fitness.js | 2 +- .../manager/plugins/status/charts/Charts.js | 4 +- .../manager/plugins/status/charts/Config.js | 2 +- client/src/share/Events.js | 51 ++++++++++--------- client/src/vm/VM.js | 2 +- 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index de120b9..865311f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -57,7 +57,8 @@ const Config = { /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing - * will be provided. Killing of organism will be done using tournament approach + * will be provided. Killing of organism will be done using random organism + * selection from population */ orgKillOnClone: true, /** @@ -70,7 +71,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 12000, + orgRainMutationPeriod: 6000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -86,12 +87,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 15000, + orgCrossoverPeriod: 100, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 15000, + orgRandomOrgPeriod: 0, /** * {Number} Amount of iterations within organism's life loop, after that we decrease * some amount of energy. If 0, then energy decreasing will be disabled. @@ -101,7 +102,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 0, + orgAlivePeriod: 20000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 6ca9727..bad910c 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -208,7 +208,7 @@ class Organisms extends Configurable { return org1; } - _clone(org) { + _clone(org, isCrossover = false) { if (this.onBeforeClone(org) === false) {return false} let pos = this.world.getNearFreePos(org.x, org.y); if (pos === false || this.createOrg(pos, org) === false) {return false} @@ -216,13 +216,13 @@ class Organisms extends Configurable { this.onClone(org, child); if (!org.alive || !child.alive) {return false} - this.parent.fire(EVENTS.CLONE, org, child); + this.parent.fire(EVENTS.CLONE, org, child, isCrossover); return true; } _crossover(org1, org2) { - this._clone(org1); + this._clone(org1, true); const orgs = this.organisms; let child = orgs.last.val; @@ -274,7 +274,8 @@ class Organisms extends Configurable { const orgAmount = this.organisms.size; const ret = org.alive && (OConfig.orgKillOnClone || orgAmount < maxOrgs) && this._clone(org); - if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this._killInTour()} + //if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this._killInTour()} + if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this.randOrg().destroy()} return ret; } diff --git a/client/src/manager/plugins/organisms/garmin/Fitness.js b/client/src/manager/plugins/organisms/garmin/Fitness.js index b2ae835..49cf8fb 100644 --- a/client/src/manager/plugins/organisms/garmin/Fitness.js +++ b/client/src/manager/plugins/organisms/garmin/Fitness.js @@ -1947,7 +1947,7 @@ class FitnessGarmin { org.energy = 0; for (let i = 0; i < len; i++) { - this._running(org, ACTIVITIES[i], i); + this._run(org, ACTIVITIES[i], i); } // // true means that result is found diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 8bdd424..322211f 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -88,10 +88,10 @@ class Charts extends Status { if (!man.canvas) {return} const conns = `${active[0] ? '^' : ''}${active[1] ? '>' : ''}${active[2] ? 'v' : ''}${active[3] ? '<' : ''}`; const ips = `ips:${status.ips}`; - const pnrg = `pnrg:${status.penergy}`; + const enrg = `enrg:${status.eenergy}`; const code = `cod:${status.code}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${pnrg} ${code}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${enrg} ${code}`; } _to12h(time) { diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index c74d21e..3a84eca 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -37,7 +37,7 @@ const Config = { killeat : {pos: '2-2|16', active: true, transparent: 0.8}, killover : {pos: '2-3|16', active: true, transparent: 0.8}, changes : {pos: '3-0|16', active: true, transparent: 0.8}, - killin : {pos: '3-1|16', active: true, transparent: 0.8}, + killin : {pos: 'topleft', active: false, transparent: 0.8}, killclone : {pos: '3-2|16', active: true, transparent: 0.8}, ips : {pos: '3-3|16', active: true, transparent: 0.8} } diff --git a/client/src/share/Events.js b/client/src/share/Events.js index c177cc5..5728c87 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -12,31 +12,32 @@ const EVENTS = { IPS : 2, CODE_RUN : 3, BACKUP : 4, - GRAB_ENERGY : 5, - UPDATE_ENERGY : 6, - KILL : 7, // general kill event - KILL_TOUR : 8, // killed during organisms tournament - KILL_NO_ENERGY : 9, // killed if zero energy - KILL_AGE : 10, // killed if max age reached - KILL_EAT : 11, // killed, because other organism has eat this one - KILL_OVERFLOW : 12, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 13, // killed, because organism step outside the world - KILL_STEP_IN : 14, // killed, because of panishment for step in from near client - KILL_CLONE : 15, // killed, because of lack of energy after clone - MUTATIONS : 16, - EAT : 17, - EAT_ORG : 18, - EAT_ENERGY : 19, - STEP : 20, - STEP_OUT : 21, - STEP_IN : 22, - BORN_ORGANISM : 23, - GET_ENERGY : 24, - DESTROY : 25, - RUN : 26, - STOP : 27, - RESET_CODE : 28, - CHECK_AT : 29 + CLONE : 5, + GRAB_ENERGY : 6, + UPDATE_ENERGY : 7, + KILL : 8, // general kill event + KILL_TOUR : 9, // killed during organisms tournament + KILL_NO_ENERGY : 10, // killed if zero energy + KILL_AGE : 11, // killed if max age reached + KILL_EAT : 12, // killed, because other organism has eat this one + KILL_OVERFLOW : 13, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 14, // killed, because organism step outside the world + KILL_STEP_IN : 15, // killed, because of punishment for step in from near client + KILL_CLONE : 16, // killed, because of lack of energy after clone + MUTATIONS : 17, + EAT : 18, + EAT_ORG : 19, + EAT_ENERGY : 20, + STEP : 21, + STEP_OUT : 22, + STEP_IN : 23, + BORN_ORGANISM : 24, + GET_ENERGY : 25, + DESTROY : 26, + RUN : 27, + STOP : 28, + RESET_CODE : 29, + CHECK_AT : 30 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index c59f9ea..ea13999 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -170,7 +170,7 @@ class VM extends Observer { if (this._code.length + adds >= OConfig.codeMaxSize) { return 0 } - this._code.splice.apply(this._code, [start, end - start + 1].concat(vm.code.slice(start1, end1 + 1))); + this._code.splice(...[start, end - start + 1].concat(vm.code.slice(start1, end1 + 1))); this._reset(); return adds; From fcfe235e8a40181befd7c1c18f3ef66cea4aaaf5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Feb 2018 15:43:01 +0200 Subject: [PATCH 162/291] added pos9() and pos16() methods for positioning of charts in 3x3, 4x4 grids #111 --- .../manager/plugins/status/charts/Charts.js | 36 +++++++++++++++---- .../manager/plugins/status/charts/Config.js | 2 +- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 322211f..a233e2a 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -13,12 +13,14 @@ const Chart = require('./Chart'); const Config = require('./Config'); const API = { - transparent: ['_transparent', 'Sets transparent level' ], - pos : ['_pos', 'Sets chart position' ], - active : ['_active', 'Activates/Deactivates chart'], - on : ['_on', 'Activates/Deactivates chart'], - off : ['_off', 'Deactivates chart' ], - reset : ['_reset', 'Resets chart data' ] + transparent: ['_transparent', 'Sets transparent level' ], + pos : ['_pos', 'Sets chart position' ], + pos9 : ['_pos9', 'Sets chart position in 3x3 grid'], + pos16 : ['_pos16', 'Sets chart position in 4x4 grid'], + active : ['_active', 'Activates/Deactivates chart' ], + on : ['_on', 'Activates/Deactivates chart' ], + off : ['_off', 'Deactivates chart' ], + reset : ['_reset', 'Resets chart data' ] }; class Charts extends Status { @@ -140,6 +142,28 @@ class Charts extends Status { */ _pos(chart, p) {this._setProperty(chart, 'pos', p)} + /** + * Positioning method, which position a chart in 3x3 grid. + * Positioning based on x,y coordinates. e.g.: pos('kill', 0,0) + * will be located in a left top corner + * @param {String} chart Chart name, e.g: 'energy', or 'lps' + * @param {Number} x X coordinate + * @param {Number} y Y coordinate + * @api + */ + _pos9(chart, x, y) {this._setProperty(chart, 'pos', `${x > 2 ? 2 : x < 0 ? 0 : x}-${y > 2 ? 2 : y < 0 ? 0 : y}|9`)} + + /** + * Positioning method, which position a chart in 4x4 grid. + * Positioning based on x,y coordinates. e.g.: pos('kill', 0,0) + * will be located in a left top corner + * @param {String} chart Chart name, e.g: 'energy', or 'lps' + * @param {Number} x X coordinate + * @param {Number} y Y coordinate + * @api + */ + _pos16(chart, x, y) {this._setProperty(chart, 'pos', `${x > 3 ? 3 : x < 0 ? 0 : x}-${y > 3 ? 3 : y < 0 ? 0 : y}|16`)} + /** * Sets current chart position. Available positions: * top, down, left, right, topleft, downleft, topright, diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 3a84eca..c74d21e 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -37,7 +37,7 @@ const Config = { killeat : {pos: '2-2|16', active: true, transparent: 0.8}, killover : {pos: '2-3|16', active: true, transparent: 0.8}, changes : {pos: '3-0|16', active: true, transparent: 0.8}, - killin : {pos: 'topleft', active: false, transparent: 0.8}, + killin : {pos: '3-1|16', active: true, transparent: 0.8}, killclone : {pos: '3-2|16', active: true, transparent: 0.8}, ips : {pos: '3-3|16', active: true, transparent: 0.8} } From c9714eb478e7b8f88ccc84dfddbf3e15a992e439 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Feb 2018 17:06:40 +0200 Subject: [PATCH 163/291] added presets 'general', 'general9', 'general16', 'kill9', 'energy' #111 --- .../manager/plugins/status/charts/Charts.js | 78 +++++++++++++++++-- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index a233e2a..4b91d05 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -13,14 +13,66 @@ const Chart = require('./Chart'); const Config = require('./Config'); const API = { - transparent: ['_transparent', 'Sets transparent level' ], - pos : ['_pos', 'Sets chart position' ], - pos9 : ['_pos9', 'Sets chart position in 3x3 grid'], - pos16 : ['_pos16', 'Sets chart position in 4x4 grid'], - active : ['_active', 'Activates/Deactivates chart' ], - on : ['_on', 'Activates/Deactivates chart' ], - off : ['_off', 'Deactivates chart' ], - reset : ['_reset', 'Resets chart data' ] + transparent: ['_transparent', 'Sets transparent level' ], + pos : ['_pos', 'Sets chart position' ], + pos9 : ['_pos9', 'Sets chart position in 3x3 grid' ], + pos16 : ['_pos16', 'Sets chart position in 4x4 grid' ], + active : ['_active', 'Activates/Deactivates chart' ], + on : ['_on', 'Activates/Deactivates chart' ], + off : ['_off', 'Deactivates chart' ], + reset : ['_reset', 'Resets chart data' ], + preset : ['_preset', 'Positioning charts according to preset'] +}; + +const PRESETS = { + general : { + lps : 'topleft', + eenergy : 'downleft', + changes : 'topright', + code : 'downright' + }, + general9 : { + lps : '0-0|9', + orgs : '0-1|9', + eenergy : '0-2|9', + changes : '1-0|9', + age : '1-1|9', + code : '1-2|9', + kill : '2-0|9', + ips : '2-1|9', + fit : '2-2|9' + }, + general16: { + lps : '0-0|16', + orgs : '0-1|16', + energy : '0-2|16', + eenergy : '0-3|16', + penergy : '1-0|16', + changes : '1-1|16', + age : '1-2|16', + code : '1-3|16', + fit : '2-0|16', + kill : '2-1|16', + killeat : '2-2|16', + killenergy: '2-3|16' + }, + kill9 : { + kill : '0-0|9', + killtour : '0-1|9', + killenergy: '0-2|9', + killage : '1-0|9', + killeat : '1-1|9', + killover : '1-2|9', + killout : '2-0|9', + killin : '2-1|9', + killclone : '2-2|9' + }, + energy : { + lps : 'topleft', + energy : 'downleft', + eenergy : 'topright', + penergy : 'downright' + } }; class Charts extends Status { @@ -223,6 +275,16 @@ class Charts extends Status { } } + _preset(name) { + if (typeof(PRESETS[name]) === 'undefined') {return} + + _each(this._charts, (inst, chart) => this._off(chart)); + _each(PRESETS[name], (pos, chart) => { + this._pos(chart, pos); + this._on(chart); + }); + } + _setProperty(chart, prop, val) { this._charts[chart][prop] = val; _has(this.cfg, `charts.${chart}.${prop}`) && (this.cfg.charts[chart][prop] = val); From 703f956916ecf461d7370c268a3187bd83daf1cd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Feb 2018 17:17:25 +0200 Subject: [PATCH 164/291] fixed an issue with invalid chart name in charts API #111 --- client/src/manager/plugins/status/charts/Charts.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 4b91d05..2d43439 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -286,6 +286,7 @@ class Charts extends Status { } _setProperty(chart, prop, val) { + if (typeof(this._charts[chart]) === 'undefined') {return} this._charts[chart][prop] = val; _has(this.cfg, `charts.${chart}.${prop}`) && (this.cfg.charts[chart][prop] = val); } From 2fb20b8bcd030061ce4fba9553c05f269d254efc Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Feb 2018 18:45:49 +0200 Subject: [PATCH 165/291] optimized grabEnergy() calls in Operators.xxx() #112 --- .../src/manager/plugins/organisms/Organism.js | 13 ++--- .../manager/plugins/organisms/Organisms.js | 1 - .../plugins/organisms/dos/Operators.js | 56 +++++++++---------- .../plugins/organisms/dos/OperatorsSpec.js | 2 +- client/src/share/Events.js | 1 - 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 9bc8f2f..8288f0f 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -15,14 +15,12 @@ const Num = require('./../../../vm/Num'); const MAX_BITS = Num.MAX_BITS; -const GRAB_ENERGY = 0; -const DESTROY = 1; -const CLONE = 2; -const KILL_NO_ENERGY = 3; -const KILL_AGE = 4; -const ITERATION = 5; +const DESTROY = 0; +const CLONE = 1; +const KILL_NO_ENERGY = 2; +const KILL_AGE = 3; +const ITERATION = 4; const ORG_EVENTS = { - GRAB_ENERGY, DESTROY, CLONE, KILL_NO_ENERGY, @@ -205,7 +203,6 @@ class Organism extends Observer { grabEnergy(amount) { if (!this._alive || !IS_NUM(amount) || amount === 0) {return true} const noEnergy = (this._energy -= amount) < 1; - this._callbacks[GRAB_ENERGY](amount + (noEnergy ? -this._energy : 0)); noEnergy && this.destroy(); return !noEnergy; } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index bad910c..274a552 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -102,7 +102,6 @@ class Organisms extends Configurable { cbs[ORG_EVENTS.KILL_AGE] = this._onKillAgeOrg.bind(this); cbs[ORG_EVENTS.ITERATION] = this._onIterationOrg.bind(this); cbs[ORG_EVENTS.CLONE] = this._onCloneOrg.bind(this); - cbs[ORG_EVENTS.GRAB_ENERGY] = () => {}; } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index fc5cd89..8e886eb 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -40,7 +40,7 @@ const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; /** * {Array} Available operators for math calculations */ -const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; +const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/(b||1), (a,b)=>a%(b||1), (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; class OperatorsDos extends Operators { constructor(offs, vars, callbacks) { @@ -108,13 +108,13 @@ class OperatorsDos extends Operators { */ onVar(num, line, org) { this.vars[VAR0(num)] = this.vars[VAR1(num)]; - org.grabEnergy(OConfig.orgOperatorWeights[0]); + org.energy -= OConfig.orgOperatorWeights[0]; return ++line; } onConst(num, line, org) { this.vars[VAR0(num)] = BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER); - org.grabEnergy(OConfig.orgOperatorWeights[0]); + org.energy -= OConfig.orgOperatorWeights[0]; return ++line; } @@ -128,11 +128,11 @@ class OperatorsDos extends Operators { const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); if (CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { - org.grabEnergy(OConfig.orgOperatorWeights[1]); + org.energy -= OConfig.orgOperatorWeights[1]; return ++line; } - org.grabEnergy(OConfig.orgOperatorWeights[1]); + org.energy -= OConfig.orgOperatorWeights[1]; return offs; } @@ -151,11 +151,11 @@ class OperatorsDos extends Operators { if (afterIteration === true) { if (++vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); - org.grabEnergy(OConfig.orgOperatorWeights[2]); + org.energy -= OConfig.orgOperatorWeights[2]; return ++line; } - org.grabEnergy(OConfig.orgOperatorWeights[2]); + org.energy -= OConfig.orgOperatorWeights[2]; return offs; } // @@ -165,18 +165,18 @@ class OperatorsDos extends Operators { vars[var0] = vars[VAR1(num)]; if (vars[var0] < vars[VAR2(num)]) { this.offs.push(line, offs); - org.grabEnergy(OConfig.orgOperatorWeights[2]); + org.energy -= OConfig.orgOperatorWeights[2]; return ++line; } - org.grabEnergy(OConfig.orgOperatorWeights[2]); + org.energy -= OConfig.orgOperatorWeights[2]; return offs; } onOperator(num, line, org) { const vars = this.vars; vars[VAR0(num)] = OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); - org.grabEnergy(OConfig.orgOperatorWeights[3]); + org.energy -= OConfig.orgOperatorWeights[3]; return ++line; } @@ -202,7 +202,7 @@ class OperatorsDos extends Operators { if (!IS_NUM(x) || !IS_NUM(y) || NORMALIZE(x, y)[2] !== DIR.NO) { vars[VAR0(num)] = 0; - org.grabEnergy(OConfig.orgOperatorWeights[4]); + org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } @@ -211,38 +211,38 @@ class OperatorsDos extends Operators { this.callbacks[EVENTS.GET_ENERGY](org, x, y, ret); vars[VAR0(num)] = ret.ret; - org.grabEnergy(OConfig.orgOperatorWeights[4]); + org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } - onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[5]); return ++line} - onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[6]); return ++line} - onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); org.grabEnergy(OConfig.orgOperatorWeights[7]); return ++line} - onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); org.grabEnergy(OConfig.orgOperatorWeights[8]); return ++line} + onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[5]; return ++line} + onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} + onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} + onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} - onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.grabEnergy(OConfig.orgOperatorWeights[9]); return ++line} - onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.grabEnergy(OConfig.orgOperatorWeights[10]); return ++line} - onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.grabEnergy(OConfig.orgOperatorWeights[11]); return ++line} - onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.grabEnergy(OConfig.orgOperatorWeights[12]); return ++line} + onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[9]; return ++line} + onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} + onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} + onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} onFromMem(num, line, org) { this.vars[VAR0(num)] = org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; - org.grabEnergy(OConfig.orgOperatorWeights[13]); + org.energy -= OConfig.orgOperatorWeights[13]; return ++line; } onToMem(num, line, org) { org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[VAR0(num)]; - org.grabEnergy(OConfig.orgOperatorWeights[14]); + org.energy -= OConfig.orgOperatorWeights[14]; return ++line; } - onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; org.grabEnergy(OConfig.orgOperatorWeights[15]); return ++line} - onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; org.grabEnergy(OConfig.orgOperatorWeights[16]); return ++line} + onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[15]; return ++line} + onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} - onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[17]); return energy} - onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.grabEnergy(OConfig.orgOperatorWeights[18]); return energy} - onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.grabEnergy(OConfig.orgOperatorWeights[19]); return energy} - onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.grabEnergy(OConfig.orgOperatorWeights[20]); return energy} + onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[17]; return energy} + onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[18]; return energy} + onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[19]; return energy} + onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[20]; return energy} _checkAt(num, line, org, x, y) { const ret = this._ret; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 2cff8ee..33788e2 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -16,7 +16,7 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking onVar() method", () => { let ops = new OperatorsDos([], [0, 0, 0, 0], new Observer()); - let org = new OrganismDos(0, 0, 0, true, {}, {[OEvents.GRAB_ENERGY]: ()=>{}}); + let org = new OrganismDos(0, 0, 0, true, {}, {}); expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); expect(ops.vars[0] === 0).toEqual(true); diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 5728c87..73c6fd0 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -13,7 +13,6 @@ const EVENTS = { CODE_RUN : 3, BACKUP : 4, CLONE : 5, - GRAB_ENERGY : 6, UPDATE_ENERGY : 7, KILL : 8, // general kill event KILL_TOUR : 9, // killed during organisms tournament From 5ec9cee180fd4b8e2b6690fe3eb3e86a80e7d2a7 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 6 Feb 2018 23:21:43 +0200 Subject: [PATCH 166/291] unit tests --- .../plugins/organisms/dos/OperatorsSpec.js | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 2cff8ee..a1f6929 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1,38 +1,40 @@ describe("client/src/organism/OperatorsDos", () => { + let OConfig = require('./../../organisms/Config'); + let cbpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 2; let OperatorsDos = require('./Operators'); let Helper = require('./../../../../../../common/src/Helper'); let Observer = require('./../../../../../../common/src/Observer'); let EVENTS = require('./../../../../share/Events').EVENTS; let EVENT_AMOUNT = require('./../../../../share/Events').EVENT_AMOUNT; let Config = require('./../../../../share/Config').Config; - let OConfig = require('./../../organisms/Config'); let OrganismDos = require('./../../organisms/dos/Organism'); let OEvents = require('./../../organisms/Organism').EVENTS; let api = require('./../../../../share/Config').api; - let cbpv = null; - beforeEach(() => {cbpv = OConfig.codeBitsPerVar;api.set('codeBitsPerVar', 2)}); - afterEach(() => api.set('codeBitsPerVar', cbpv)); + afterAll(() => OConfig.codeBitsPerVar = cbpv); it("Checking onVar() method", () => { - let ops = new OperatorsDos([], [0, 0, 0, 0], new Observer()); - let org = new OrganismDos(0, 0, 0, true, {}, {[OEvents.GRAB_ENERGY]: ()=>{}}); - - expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 0).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 0).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); + const cbs = { + [OEvents.GRAB_ENERGY] : () => {}, + [OEvents.DESTROY] : () => {}, + [OEvents.CLONE] : () => {}, + [OEvents.KILL_NO_ENERGY] : () => {}, + [OEvents.KILL_AGE] : () => {}, + [OEvents.ITERATION] : () => {} + }; + let ops = new OperatorsDos([], [0, 1, 2, 3], cbs); + let org = new OrganismDos('0', 0, 0, true, {}, cbs); + + expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 + expect(ops.vars).toEqual([0, 1, 2, 1]); + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.vars).toEqual([0, 1, 2, 1]); expect(ops.onVar(0x0000ffff, 0, org)).toEqual(1); - expect(ops.vars[0] === 0x3fff).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 0).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); + // expect(ops.vars[0] === 0x3fff).toEqual(true); + // expect(ops.vars[1] === 0).toEqual(true); + // expect(ops.vars[2] === 0).toEqual(true); + // expect(ops.vars[3] === 0).toEqual(true); org.destroy(); ops.destroy(); From 2c8919beebeead942a898c5a0b2723cf13f511e9 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 7 Feb 2018 01:17:25 +0200 Subject: [PATCH 167/291] fixed critical error in cloning mechanism increased amount of available color or organisms (5 times more) --- .../src/manager/plugins/organisms/Organism.js | 10 +++++++--- .../manager/plugins/organisms/Organisms.js | 20 +++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 8288f0f..a89dd7c 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -37,7 +37,7 @@ class Organism extends Observer { * @returns {Number} RGB value */ static _getColor(index) { - const frequency = 0.05; + const frequency = 0.01; const r = Math.sin(frequency * index ) * 127 + 128; const g = Math.sin(frequency * index + 2) * 127 + 128; @@ -266,8 +266,12 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > this._nextClone) && this.vm.size > 0 && this._callbacks[CLONE](this) && this._alive) { - this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1); + if ((this._energy > this._nextClone) && this.vm.size > 0) { + const ratio = this._energy / this._nextClone; + const clones = Math.floor(ratio); + if (this._callbacks[CLONE](this, clones) && this._alive) { + this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * (ratio - clones); + } } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 274a552..bbeaf19 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -268,15 +268,23 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - _onCloneOrg(org) { - const maxOrgs = OConfig.orgMaxOrgs; - const orgAmount = this.organisms.size; - const ret = org.alive && (OConfig.orgKillOnClone || orgAmount < maxOrgs) && this._clone(org); + _onCloneOrg(org, amount) { + const maxOrgs = OConfig.orgMaxOrgs; + const killOnClone = OConfig.orgKillOnClone; + + for (let i = 0; i < amount; i++) { + if (org.alive && (killOnClone || this.organisms.size < maxOrgs)) { + this._clone(org) + } + } //if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this._killInTour()} - if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this.randOrg().destroy()} + const orgAmount = this.organisms.size; + if (killOnClone && orgAmount >= maxOrgs) { + for (let i = maxOrgs; i < orgAmount; i++) {this.randOrg().destroy()} + } - return ret; + return true; } _killInTour() { From d828f6e4abf43da1308cec2a91e5b4d9c01ebf55 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 8 Feb 2018 11:07:35 +0200 Subject: [PATCH 168/291] reverted back Observer/event based approach. Observer was optimized ~ 30% #114 --- .../src/manager/plugins/organisms/Organism.js | 24 ++++------ .../manager/plugins/organisms/Organisms.js | 20 ++++---- .../plugins/organisms/dos/Operators.js | 14 +++--- .../plugins/organisms/dos/OperatorsSpec.js | 1 - .../manager/plugins/organisms/dos/Organism.js | 5 +- .../plugins/organisms/dos/Organisms.js | 14 +++--- .../plugins/organisms/garmin/Operators.js | 7 ++- .../plugins/organisms/garmin/Organism.js | 9 ++-- client/src/share/Events.js | 48 +++++++++---------- client/src/vm/Operators.js | 12 ++--- client/src/vm/VM.js | 12 ++--- common/src/Observer.js | 38 +++++++++------ 12 files changed, 104 insertions(+), 100 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index a89dd7c..ccf8f7a 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -71,14 +71,12 @@ class Organism extends Observer { * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Function} operatorCls Class of operators - * @param {Object} callbacks Map of callback functions * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, operatorCls, callbacks, parent = null) { + constructor(id, x, y, alive, item, operatorCls, parent = null) { super(EVENT_AMOUNT); this._operatorCls = operatorCls; - this._callbacks = callbacks; if (parent === null) {this._create()} else {this._clone(parent)} @@ -109,7 +107,6 @@ class Organism extends Observer { get colorIndex() {return this._colorIndex} get mem() {return this._mem} get posId() {return Helper.posId(this._x, this._y)} - get callbacks() {return this._callbacks} set x(newX) {this._x = newX} set y(newY) {this._y = newY} @@ -135,7 +132,7 @@ class Organism extends Observer { this._alive && this._updateClone(); const lines = this._alive ? this.onRun() : 0; if (this._alive) { - this._callbacks[ITERATION](lines, this); + this.fire(ITERATION, lines, this); this._alive && this._updateAge(); this._alive && this._updateEnergy(); } @@ -217,7 +214,7 @@ class Organism extends Observer { } destroy() { - this._callbacks[DESTROY](this); + this.fire(DESTROY, this); this._alive = false; this._energy = 0; this._startEnergy = 0; @@ -227,7 +224,6 @@ class Organism extends Observer { this.vm && this.vm.destroy(); this.vm = null; this._operatorCls = null; - this._callbacks = null; this._nextClone = null; this._iterations = -1; @@ -235,7 +231,7 @@ class Organism extends Observer { } _create() { - this.vm = new VM(this._callbacks, this._operatorCls); + this.vm = new VM(this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; this._colorIndex = OConfig.orgStartColor * MAX_BITS; @@ -249,7 +245,7 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this._callbacks, this._operatorCls, parent.vm); + this.vm = new VM(this, this._operatorCls, parent.vm); this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; @@ -269,8 +265,8 @@ class Organism extends Observer { if ((this._energy > this._nextClone) && this.vm.size > 0) { const ratio = this._energy / this._nextClone; const clones = Math.floor(ratio); - if (this._callbacks[CLONE](this, clones) && this._alive) { - this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * (ratio - clones); + if (this.fire(CLONE, this, clones) && this._alive) { + this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * (1 - (ratio - clones)); } } } @@ -284,7 +280,7 @@ class Organism extends Observer { const needDestroy = this._iterations >= alivePeriod && alivePeriod > 0; if (needDestroy) { - this._callbacks[KILL_AGE](this); + this.fire(KILL_AGE, this); this.destroy(); } @@ -298,7 +294,7 @@ class Organism extends Observer { */ _updateEnergy() { if (this._energy < 1) { - this._callbacks[KILL_NO_ENERGY](this); + this.fire(KILL_NO_ENERGY, this); this.destroy(); return true; } @@ -306,7 +302,7 @@ class Organism extends Observer { let grabSize = this.vm.size; if (grabSize < 1) {grabSize = 1} - (this._energy <= grabSize) && this._callbacks[KILL_NO_ENERGY](this); + (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index bbeaf19..aadc9d0 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -87,7 +87,6 @@ class Organisms extends Configurable { this.randOrgItem = this.organisms.first; this.positions = manager.positions; this.world = manager.world; - const cbs = this.callbacks = {}; this._mutator = new Mutator(manager, this); this._onIterationCb = this._onIteration.bind(this); @@ -96,13 +95,6 @@ class Organisms extends Configurable { this.reset(); Helper.override(manager, 'onIteration', this._onIterationCb); Helper.override(manager, 'onLoop', this._onLoopCb); - - cbs[ORG_EVENTS.DESTROY] = this._onKillOrg.bind(this); - cbs[ORG_EVENTS.KILL_NO_ENERGY] = this._onKillNoEnergyOrg.bind(this); - cbs[ORG_EVENTS.KILL_AGE] = this._onKillAgeOrg.bind(this); - cbs[ORG_EVENTS.ITERATION] = this._onIterationOrg.bind(this); - cbs[ORG_EVENTS.CLONE] = this._onCloneOrg.bind(this); - } destroy() { @@ -116,11 +108,18 @@ class Organisms extends Configurable { this._mutator = null; this._onIterationCb = null; this._onLoopCb = null; - this.callbacks = null; super.destroy(); } + addOrgHandlers(org) { + org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); + org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); + org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); + org.on(ORG_EVENTS.ITERATION, this._onIterationOrg.bind(this)); + org.on(ORG_EVENTS.CLONE, this._onCloneOrg.bind(this)); + } + reset() { this._orgId = 0; } @@ -142,9 +141,10 @@ class Organisms extends Configurable { const orgs = this.organisms; orgs.add(null); let last = orgs.last; - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, this.callbacks, parent); + let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, parent); last.val = org; + this.addOrgHandlers(org); this.move(-1, -1, pos.x, pos.y, org); this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 8e886eb..d1e19e6 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -43,8 +43,8 @@ const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/(b||1), (a,b)=>a%(b||1), (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; class OperatorsDos extends Operators { - constructor(offs, vars, callbacks) { - super(offs, vars, callbacks); + constructor(offs, vars, obs) { + super(offs, vars, obs); /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -78,7 +78,7 @@ class OperatorsDos extends Operators { this.onCheckDown.bind(this) ]; /** - * {Object} Reusable object to pass it as a parameter to this.callbacks(..., ret) + * {Object} Reusable object to pass it as a parameter to this.fire(..., ret) */ this._ret = {ret: 0, x: 0, y: 0}; //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; @@ -208,7 +208,7 @@ class OperatorsDos extends Operators { const ret = this._ret; ret.ret = 0; - this.callbacks[EVENTS.GET_ENERGY](org, x, y, ret); + this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); vars[VAR0(num)] = ret.ret; org.energy -= OConfig.orgOperatorWeights[4]; @@ -248,7 +248,7 @@ class OperatorsDos extends Operators { const ret = this._ret; ret.ret = 0; - this.callbacks[EVENTS.CHECK_AT](x, y, ret); + this.obs.fire(EVENTS.CHECK_AT, x, y, ret); this.vars[VAR0(num)] = ret.ret; return ++line; } @@ -259,7 +259,7 @@ class OperatorsDos extends Operators { const ret = this._ret; ret.ret = amount; - this.callbacks[EVENTS.EAT](org, x, y, ret); + this.obs.fire(EVENTS.EAT, org, x, y, ret); org.energy += ret.ret; return ret.ret; @@ -269,7 +269,7 @@ class OperatorsDos extends Operators { const ret = this._ret; ret.ret = 0; - this.callbacks[EVENTS.STEP](org, x1, y1, x2, y2, ret); + this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2, ret); if (ret.ret > 0) { org.x = ret.x; org.y = ret.y; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index a1f6929..eafa51d 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -16,7 +16,6 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking onVar() method", () => { const cbs = { - [OEvents.GRAB_ENERGY] : () => {}, [OEvents.DESTROY] : () => {}, [OEvents.CLONE] : () => {}, [OEvents.KILL_NO_ENERGY] : () => {}, diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index e895369..7ba1446 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -17,11 +17,10 @@ class OrganismDos extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Object} callbacks Map of callback functions * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, callbacks, parent = null) { - super(id, x, y, alive, item, Operators, callbacks, parent); + constructor(id, x, y, alive, item, parent = null) { + super(id, x, y, alive, item, Operators, parent); } onRun() { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 0d5c33f..735e28d 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -34,12 +34,6 @@ class Organisms extends BaseOrganisms { this._onStepInCb = this._onStepIn.bind(this); this.parent.on(EVENTS.STEP_IN, this._onStepInCb); - - const cbs = this.callbacks; - cbs[EVENTS.GET_ENERGY] = this._onGetEnergy.bind(this); - cbs[EVENTS.EAT] = this._onEat.bind(this); - cbs[EVENTS.STEP] = this._onStep.bind(this); - cbs[EVENTS.CHECK_AT] = this._onCheckAt.bind(this); } destroy() { @@ -97,6 +91,14 @@ class Organisms extends BaseOrganisms { child.alive && (child.startEnergy = child.energy); } + addOrgHandlers(org) { + super.addOrgHandlers(org); + org.on(EVENTS.GET_ENERGY, this._onGetEnergy.bind(this)); + org.on(EVENTS.EAT, this._onEat.bind(this)); + org.on(EVENTS.STEP, this._onStep.bind(this)); + org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); + } + /** * Creates instance of an organism * @param {Array} args Custom organism arguments diff --git a/client/src/manager/plugins/organisms/garmin/Operators.js b/client/src/manager/plugins/organisms/garmin/Operators.js index 99ce939..b939717 100644 --- a/client/src/manager/plugins/organisms/garmin/Operators.js +++ b/client/src/manager/plugins/organisms/garmin/Operators.js @@ -9,7 +9,6 @@ const Helper = require('./../../../../../../common/src/Helper'); const Operators = require('./../../../../vm/Operators'); const Num = require('./../../../../vm/Num'); -const Config = require('./../../../../share/Config').Config; const OConfig = require('./../Config'); /** @@ -25,8 +24,8 @@ const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; class OperatorsGarmin extends Operators { - constructor(offs, vars, callbacks) { - super(offs, vars, callbacks); + constructor(offs, vars, obs) { + super(offs, vars, obs); /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -53,7 +52,7 @@ class OperatorsGarmin extends Operators { this._OPERATORS = [ (a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b) ]; - this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; + //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // // We have to set amount of available operators for correct // working of mutations of operators. diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index 7070a63..590d476 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -6,7 +6,6 @@ */ const Organism = require('./../Organism').Organism; const Operators = require('./Operators'); -const Config = require('./../../../../share/Config').Config; const EVENTS = require('./../../../../share/Events').EVENTS; const Fitness = require('./Fitness'); @@ -20,11 +19,11 @@ class OrganismGarmin extends Organism { * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located - * @param {Object} callbacks Map of callback functions + * @param {Observer} obs Observer for sending external events * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, callbacks, parent = null) { - super(id, x, y, alive, item, Operators, callbacks, parent); + constructor(id, x, y, alive, item, obs, parent = null) { + super(id, x, y, alive, item, Operators, obs, parent); this._needRun = true; @@ -36,7 +35,7 @@ class OrganismGarmin extends Organism { } onRun() { - if (Fitness.run(this)) {this.callbacks[EVENTS.STOP](this)} + if (Fitness.run(this)) {this.obs.fire(EVENTS.STOP, this)} this._needRun = false; } diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 73c6fd0..a2c7a7b 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -13,30 +13,30 @@ const EVENTS = { CODE_RUN : 3, BACKUP : 4, CLONE : 5, - UPDATE_ENERGY : 7, - KILL : 8, // general kill event - KILL_TOUR : 9, // killed during organisms tournament - KILL_NO_ENERGY : 10, // killed if zero energy - KILL_AGE : 11, // killed if max age reached - KILL_EAT : 12, // killed, because other organism has eat this one - KILL_OVERFLOW : 13, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 14, // killed, because organism step outside the world - KILL_STEP_IN : 15, // killed, because of punishment for step in from near client - KILL_CLONE : 16, // killed, because of lack of energy after clone - MUTATIONS : 17, - EAT : 18, - EAT_ORG : 19, - EAT_ENERGY : 20, - STEP : 21, - STEP_OUT : 22, - STEP_IN : 23, - BORN_ORGANISM : 24, - GET_ENERGY : 25, - DESTROY : 26, - RUN : 27, - STOP : 28, - RESET_CODE : 29, - CHECK_AT : 30 + UPDATE_ENERGY : 6, + KILL : 7, // general kill event + KILL_TOUR : 8, // killed during organisms tournament + KILL_NO_ENERGY : 9, // killed if zero energy + KILL_AGE : 10, // killed if max age reached + KILL_EAT : 11, // killed, because other organism has eat this one + KILL_OVERFLOW : 12, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 13, // killed, because organism step outside the world + KILL_STEP_IN : 14, // killed, because of punishment for step in from near client + KILL_CLONE : 15, // killed, because of lack of energy after clone + MUTATIONS : 16, + EAT : 17, + EAT_ORG : 18, + EAT_ENERGY : 19, + STEP : 20, + STEP_OUT : 21, + STEP_IN : 22, + BORN_ORGANISM : 23, + GET_ENERGY : 24, + DESTROY : 25, + RUN : 26, + STOP : 27, + RESET_CODE : 28, + CHECK_AT : 29 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/vm/Operators.js b/client/src/vm/Operators.js index 24e67fa..b55b69f 100644 --- a/client/src/vm/Operators.js +++ b/client/src/vm/Operators.js @@ -5,7 +5,7 @@ * @author flatline */ class Operators { - constructor(offs, vars, callbacks) { + constructor(offs, vars, obs) { /** * {Array} Array of offsets for closing braces. For 'for', 'if' * and other operators. @@ -16,15 +16,15 @@ class Operators { */ this.vars = vars; /** - * {Observer} Callbacks map for calling outside callbacks + * {Observer} Observer for sending external events */ - this.callbacks = callbacks; + this.obs = obs; } destroy() { - this.offs = null; - this.vars = null; - this.callbacks = null; + this.offs = null; + this.vars = null; + this.obs = null; } /** diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index ea13999..1df0dc1 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -27,14 +27,14 @@ class VM extends Observer { /** * Creates VM instance. parent is used if VM instance is in a * cloning mode and we have to create a copy of it. - * @param {Object} callbacks Callbacks map for calling outside methods + * @param {Observer} obs observer for external events firing * @param {Function} operatorCls Class of operators * @param {VM} parent Parent VM instance in case of cloning */ - constructor(callbacks, operatorCls, parent = null) { + constructor(obs, operatorCls, parent = null) { super(EVENT_AMOUNT); - this._callbacks = callbacks; + this._obs = obs; /** * {Function} Class of operators, with implementation of all available * script parts for current VM instance @@ -50,7 +50,7 @@ class VM extends Observer { /** * {Function} Class, which implement all supported operators */ - this._operators = new operatorCls(this._offsets, this._vars, callbacks); + this._operators = new operatorCls(this._offsets, this._vars, obs); this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; this._line = 0; @@ -78,7 +78,7 @@ class VM extends Observer { this._vars = json.vars; this._code = json.code; this._line = json.line; - this._operators = new this._operatorCls(this._offsets, this._vars, this._callbacks); + this._operators = new this._operatorCls(this._offsets, this._vars, this._obs); } /** @@ -132,7 +132,7 @@ class VM extends Observer { this._offsets = null; this._vars = null; this._code = null; - this._callbacks = null; + this._obs = null; this._ops = null; super.destroy(); diff --git a/common/src/Observer.js b/common/src/Observer.js index ea64fc5..d01f931 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -1,7 +1,9 @@ /** * Observer implementation. May fire, listen(on()) and clear all the event * handlers. This class is optimized for speed. This is why it works with - * array of numbers as events instead of frequent strings. + * array of numbers as events instead of frequent strings and uses Object + * for storing event handlers. It fast on fire and slow on removing event + * handlers (off() method). * * Usage: * import {EVENTS} from '.../Events.js' @@ -24,20 +26,28 @@ class Observer { this._resetEvents(); } - on (event, handler) { - if (typeof(this._handlers[event]) === 'undefined') {return false} - this._handlers[event].push(handler); + on(event, handler) { + const eventObj = this._handlers[event]; + if (typeof(eventObj) === 'undefined') {return false} + eventObj[eventObj.amount++] = handler; return true; } - off (event, handler) { - let index; + off(event, handler) { + let index = -1; let handlers = this._handlers[event]; + let len = handlers.amount; if (handlers) { - if ((index = handlers.indexOf(handler)) < 0) {return false} - handlers.splice(index, 1); + for (let i = 0; i < len; i++) { + if (handlers[i] === handler) { + index = i; + handlers.amount = --len; + } + index > -1 && (handlers[i] = handlers[i+1]); + } + delete handlers[handlers.amount]; } return true; @@ -50,9 +60,9 @@ class Observer { * @param {*} args List of arguments * @param args */ - fire (event, ...args) { - const handlers = this._handlers[event] || []; - for (let i = 0, len = handlers.length; i < len; i++) { + fire(event, ...args) { + const handlers = this._handlers[event]; + for (let i = 0, len = handlers.amount; i < len; i++) { handlers[i](...args); } } @@ -62,7 +72,7 @@ class Observer { * to use on()/off() methods for working with events, but max * event index set in constructor will be the same. */ - clear () { + clear() { this._resetEvents(); } @@ -72,8 +82,8 @@ class Observer { _resetEvents() { const len = this._maxIndex; - const handlers = this._handlers = new Array(len); - for (let i = 0; i < len; i++) {handlers[i] = []} + const handlers = this._handlers = {}; + for (let i = 0; i < len; i++) {handlers[i] = {amount: 0}} } } From a9cbcfb15981070b38a24b1070df36a97ba15447 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 8 Feb 2018 21:46:46 +0200 Subject: [PATCH 169/291] small optimizations of DOS language fixed Infinity/undefined values inside DOS script --- .../src/manager/plugins/organisms/Config.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 6 ++-- .../plugins/organisms/dos/Operators.js | 19 ++++++----- .../plugins/organisms/dos/Organisms.js | 11 +++---- .../plugins/organisms/garmin/Operators.js | 2 +- common/src/Helper.js | 32 +++++++++++++++++++ 6 files changed, 50 insertions(+), 22 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 865311f..20a9261 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -60,7 +60,7 @@ const Config = { * will be provided. Killing of organism will be done using random organism * selection from population */ - orgKillOnClone: true, + orgKillOnClone: false, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index ccf8f7a..4e3740c 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -199,9 +199,7 @@ class Organism extends Observer { grabEnergy(amount) { if (!this._alive || !IS_NUM(amount) || amount === 0) {return true} - const noEnergy = (this._energy -= amount) < 1; - noEnergy && this.destroy(); - return !noEnergy; + (this._energy -= amount) < 1 && this.destroy(); } // TODO: describe fitness in details @@ -266,7 +264,7 @@ class Organism extends Observer { const ratio = this._energy / this._nextClone; const clones = Math.floor(ratio); if (this.fire(CLONE, this, clones) && this._alive) { - this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * (1 - (ratio - clones)); + this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * ((1 - (ratio - clones)) || 1); } } } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index d1e19e6..c927470 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -17,7 +17,7 @@ const Num = require('./../../../../vm/Num'); * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.normalize() */ -const NORMALIZE = Helper.normalize; +const IN_WORLD = Helper.inWorld; /** * {Function} Just a shortcuts */ @@ -28,7 +28,6 @@ const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; const BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; const FOUR_BITS = 4; const BITS_FOR_NUMBER = 16; -const IS_NUM = Helper.isNumeric; const CONDITION_BITS = 2; const BITS = Num.getBits; @@ -200,17 +199,17 @@ class OperatorsDos extends Operators { let x = vars[VAR1(num)]; let y = vars[VAR2(num)]; - if (!IS_NUM(x) || !IS_NUM(y) || NORMALIZE(x, y)[2] !== DIR.NO) { - vars[VAR0(num)] = 0; + if (!IN_WORLD(x, y)) { + const ret = this._ret; + ret.ret = 0; + this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); + vars[VAR0(num)] = ret.ret; + org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } - const ret = this._ret; - ret.ret = 0; - this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); - vars[VAR0(num)] = ret.ret; - + vars[VAR0(num)] = 0; org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } @@ -255,7 +254,7 @@ class OperatorsDos extends Operators { _eat(org, num, x, y) { const amount = this.vars[VAR1(num)]; - if (!IS_NUM(amount) || amount <= 0) {return 0} + if (amount <= 0) {return 0} const ret = this._ret; ret.ret = amount; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 735e28d..89ab8f2 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -21,7 +21,8 @@ const DIR = require('./../../../../../../common/src/Directions').DIR; * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.normalize() */ -const NORMALIZE = Helper.normalize; +const NORMALIZE = Helper.normalize; +const NORMALIZE_NO_DIR = Helper.normalizeNoDir; /** * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.posId() @@ -155,10 +156,9 @@ class Organisms extends BaseOrganisms { // Amount of eat energy depends on organism size. Small organisms // eat less, big - more // - const eat = ret.ret / (OConfig.codeMaxSize / (org.vm.size || 1)); - let dir; + const eat = ret.ret / ((OConfig.codeMaxSize / (org.vm.size || 1)) || 1); - [x, y, dir] = NORMALIZE(x, y); + [x, y] = NORMALIZE_NO_DIR(x, y); const posId = POSID(x, y); if (typeof(positions[posId]) === 'undefined') { @@ -254,8 +254,7 @@ class Organisms extends BaseOrganisms { const org = this.positions[POSID(x, y)]; if (typeof(org) === 'undefined') { - let dir; - [x, y, dir] = NORMALIZE(x, y); + [x, y] = NORMALIZE_NO_DIR(x, y); ret.ret = this.world.getDot(x, y); } else { ret.ret = org.energy; diff --git a/client/src/manager/plugins/organisms/garmin/Operators.js b/client/src/manager/plugins/organisms/garmin/Operators.js index b939717..8667303 100644 --- a/client/src/manager/plugins/organisms/garmin/Operators.js +++ b/client/src/manager/plugins/organisms/garmin/Operators.js @@ -50,7 +50,7 @@ class OperatorsGarmin extends Operators { * {Array} Available operators for math calculations */ this._OPERATORS = [ - (a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/b, (a,b)=>a%b, (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b) + (a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/(b||1), (a,b)=>a%(b||1), (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b) ]; //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // diff --git a/common/src/Helper.js b/common/src/Helper.js index 6ae7b40..f29e7ef 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -153,6 +153,38 @@ class Helper { return [x, y, dir]; } + /** + * Does normalization of X and Y coordinates. It's used + * in cyclical mode for checking if we out of bound (world). + * In non cyclical mode it just returns the same coordinates. + * Usage: [x, y] = Helper.normalizeNoDir(10, -1); // 10, 100 (height - 1) + * 'dir' parameter means 'direction' and will be set only if + * one or two coordinates are out of bounds (world). Otherwise + * 'dir' parameter will be set to DIR.NO value. + * @param {Number} x + * @param {Number} y + * @returns {[x,y]} + */ + static normalizeNoDir(x, y) { + if (x < 0) {x = Config.worldWidth - 1} + else if (x >= Config.worldWidth) {x = 0} + + if (y < 0) {y = Config.worldHeight - 1} + else if (y >= Config.worldHeight) {y = 0} + + return [x, y]; + } + + /** + * Checks if specified coordinates are within current world + * @param {Number} x + * @param {Number} y + * @returns {Boolean} + */ + static inWorld(x, y) { + return !(x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight); + } + /** * Flips X or Y to the opposite coordinates. e.g: * width=10, height=10, x=0, y=1 -> x=9, y=1 From e8880faffd410ce0eb83a182ec1409dc2878b653 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 9 Feb 2018 01:57:11 +0200 Subject: [PATCH 170/291] fixed Infinity, undefined, NaN values in DOS scripts DOS speed optimizations --- .../src/manager/plugins/organisms/Config.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 11 +++------ .../plugins/organisms/dos/Operators.js | 24 +++++++++++++++---- .../plugins/organisms/dos/OrganismSpec.js | 2 +- .../plugins/organisms/dos/Organisms.js | 8 +++---- client/src/view/World.js | 2 +- client/src/vm/VM.js | 2 +- common/src/Helper.js | 2 +- 8 files changed, 32 insertions(+), 21 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 20a9261..865311f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -60,7 +60,7 @@ const Config = { * will be provided. Killing of organism will be done using random organism * selection from population */ - orgKillOnClone: false, + orgKillOnClone: true, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 4e3740c..5d1c9db 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -132,9 +132,9 @@ class Organism extends Observer { this._alive && this._updateClone(); const lines = this._alive ? this.onRun() : 0; if (this._alive) { - this.fire(ITERATION, lines, this); + this._updateEnergy(); + this._alive && this.fire(ITERATION, lines, this); this._alive && this._updateAge(); - this._alive && this._updateEnergy(); } return true; @@ -197,11 +197,6 @@ class Organism extends Observer { this._mem = json.mem.slice(); } - grabEnergy(amount) { - if (!this._alive || !IS_NUM(amount) || amount === 0) {return true} - (this._energy -= amount) < 1 && this.destroy(); - } - // TODO: describe fitness in details fitness() { // TODO: check these variants @@ -301,7 +296,7 @@ class Organism extends Observer { if (grabSize < 1) {grabSize = 1} (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); - return this.grabEnergy(this._energy < grabSize ? this._energy : grabSize); + return this._energy -= (this._energy < grabSize ? this._energy : grabSize); } } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index c927470..bc402a5 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -6,7 +6,6 @@ * * @author flatline */ -const DIR = require('./../../../../../../common/src/Directions').DIR; const Helper = require('./../../../../../../common/src/Helper'); const EVENTS = require('./../../../../../src/share/Events').EVENTS; const OConfig = require('./../Config'); @@ -18,7 +17,8 @@ const Num = require('./../../../../vm/Num'); * much faster, then Helper.normalize() */ const IN_WORLD = Helper.inWorld; -/** +const IS_FINITE = Number.isFinite; + /** * {Function} Just a shortcuts */ const VAR0 = Num.getVar0; @@ -30,7 +30,6 @@ const FOUR_BITS = 4; const BITS_FOR_NUMBER = 16; const CONDITION_BITS = 2; const BITS = Num.getBits; - /** * {Array} Available conditions for if operator. Amount should be * the same like (1 << BITS_PER_VAR) @@ -39,7 +38,24 @@ const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; /** * {Array} Available operators for math calculations */ -const OPERATORS = [(a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/(b||1), (a,b)=>a%(b||1), (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b)]; +const OPERATORS = [ + (a,b) => {const v=a+b; return IS_FINITE(v)?v:0}, + (a,b) => {const v=a-b; return IS_FINITE(v)?v:0}, + (a,b) => {const v=a*b; return IS_FINITE(v)?v:0}, + (a,b) => {const v=a/b; return IS_FINITE(v)?v:0}, + (a,b) => {const v=a%b; return IS_FINITE(v)?v:0}, + (a,b) => a&b, + (a,b) => a|b, + (a,b) => a^b, + (a,b) => a>>b, + (a,b) => a< a>>>b, + (a,b) => +(a +(a>b), + (a,b) => +(a===b), + (a,b) => +(a!==b), + (a,b) => +(a<=b) +]; class OperatorsDos extends Operators { constructor(offs, vars, obs) { diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index f066a40..325a4c4 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -168,7 +168,7 @@ describe("client/src/organism/OrganismDos", () => { let org = new OrganismDos(0, 1, 2, true, null, () => {}); const energy = org.energy; - org.grabEnergy(10); + org.energy -= 10; expect(org.energy).toEqual(energy - 10); org.destroy(); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 89ab8f2..ae0bdb1 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -85,9 +85,9 @@ class Organisms extends BaseOrganisms { energy--; } orgEnergy <= energy && this.parent.fire(EVENTS.KILL_CLONE, org); - org.grabEnergy(energy); + org.energy -= energy; childEnergy <= (childEnergy - energy) && this.parent.fire(EVENTS.KILL_CLONE, child); - child.grabEnergy(childEnergy - energy); + child.energy -= (childEnergy - energy); org.alive && (org.startEnergy = org.energy); child.alive && (child.startEnergy = child.energy); } @@ -172,7 +172,7 @@ class Organisms extends BaseOrganisms { const victimOrg = positions[posId]; ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); victimOrg.energy <= ret.ret && this.parent.fire(EVENTS.KILL_EAT, victimOrg); - victimOrg.grabEnergy(ret.ret); + victimOrg.energy -= ret.ret; } } @@ -246,7 +246,7 @@ class Organisms extends BaseOrganisms { org.y = y; const energy = (((org.energy * OConfig.orgStepEnergySpendPercent) + 0.5) << 1) >>> 1; (org.energy <= energy) && this.parent.fire(EVENTS.KILL_STEP_IN, org); - org.grabEnergy(energy); + org.energy -= energy; } } diff --git a/client/src/view/World.js b/client/src/view/World.js index 782fbf3..76010c7 100644 --- a/client/src/view/World.js +++ b/client/src/view/World.js @@ -63,7 +63,7 @@ class World extends Observer { } getDot(x, y) { - if (x < 0 || x >= this._width || y < 0 || y >= this._height) {return false} + if (x < 0 || x >= this._width || y < 0 || y >= this._height) {return 0} return this._data[x][y]; } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 1df0dc1..8bd10b8 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -99,7 +99,7 @@ class VM extends Observer { let line = this._line; let ret = false; - while (len > 0 && org.alive) { + while (len > 0 && org.energy > 0) { line = ops[code[line] >>> VAR_BITS_OFFS](code[line], line, org, lines, ret); // // We reach the end of the script and have to run it from the beginning diff --git a/common/src/Helper.js b/common/src/Helper.js index f29e7ef..71eeef8 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -182,7 +182,7 @@ class Helper { * @returns {Boolean} */ static inWorld(x, y) { - return !(x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight); + return x >= 0 && x < Config.worldWidth && y >= 0 && y < Config.worldHeight; } /** From 7e00bdea9929fcebede585c10831a7fa1a97199b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 12 Feb 2018 10:21:11 +0200 Subject: [PATCH 171/291] Added pinning canvas width/height to the screen size clicking on fullscreen button #111 Removed unused method Canvas.text() --- client/src/view/Canvas.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index ce83c7f..43b7a50 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -19,7 +19,6 @@ class Canvas { this._height = height; this._canvasEl = doc.querySelector('#' + id); this._ctx = this._canvasEl.getContext('2d'); - this._text = {x: 0, y: 0, t: ''}; this._imgData = this._ctx.createImageData(this._width, this._height); this._data = this._imgData.data; this._animate = this._onAnimate.bind(this); @@ -51,14 +50,6 @@ class Canvas { this._onAnimate(); } - text(x, y, text) { - const t = this._text; - - t.t = text; - t.x = x; - t.y = y; - } - dot(x, y, color) { this._dot(x, y, color); } @@ -111,16 +102,16 @@ class Canvas { el.onclick = () => { this._panZoom.zoomAbs(0, 0, 1.0); this._panZoom.moveTo(0, 0); + this._canvasEl.style.width = '100%'; + this._canvasEl.style .height = '100%'; + }; return el; } _onAnimate() { - const text = this._text; - this._ctx.putImageData(this._imgData, 0, 0); - this._ctx.fillText(text.t, text.x, text.y); if (this._visualize === true) { window.requestAnimationFrame(this._animate); From dadce2c1ba67eeb39f247f2772690e8c8c739874 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 13 Feb 2018 11:08:05 +0200 Subject: [PATCH 172/291] fixed few tests #83 --- common/src/Observer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/Observer.js b/common/src/Observer.js index d01f931..c1a6905 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -37,7 +37,7 @@ class Observer { off(event, handler) { let index = -1; let handlers = this._handlers[event]; - let len = handlers.amount; + let len = handlers && handlers.amount || 0; if (handlers) { for (let i = 0; i < len; i++) { From 7a041bb55d609f126917c76ffa7a7e54d038c584 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 14 Feb 2018 10:05:13 +0200 Subject: [PATCH 173/291] fixed few tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 127 +++++++++--------- 1 file changed, 60 insertions(+), 67 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index eafa51d..9f7a141 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -3,81 +3,74 @@ describe("client/src/organism/OperatorsDos", () => { let cbpv = OConfig.codeBitsPerVar; OConfig.codeBitsPerVar = 2; let OperatorsDos = require('./Operators'); - let Helper = require('./../../../../../../common/src/Helper'); let Observer = require('./../../../../../../common/src/Observer'); let EVENTS = require('./../../../../share/Events').EVENTS; let EVENT_AMOUNT = require('./../../../../share/Events').EVENT_AMOUNT; - let Config = require('./../../../../share/Config').Config; + //let Config = require('./../../../../share/Config').Config; let OrganismDos = require('./../../organisms/dos/Organism'); - let OEvents = require('./../../organisms/Organism').EVENTS; - let api = require('./../../../../share/Config').api; + //let OEvents = require('./../../organisms/Organism').EVENTS; + //let api = require('./../../../../share/Config').api; afterAll(() => OConfig.codeBitsPerVar = cbpv); - it("Checking onVar() method", () => { - const cbs = { - [OEvents.DESTROY] : () => {}, - [OEvents.CLONE] : () => {}, - [OEvents.KILL_NO_ENERGY] : () => {}, - [OEvents.KILL_AGE] : () => {}, - [OEvents.ITERATION] : () => {} - }; - let ops = new OperatorsDos([], [0, 1, 2, 3], cbs); - let org = new OrganismDos('0', 0, 0, true, {}, cbs); - - expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 - expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 - expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x0000ffff, 0, org)).toEqual(1); - // expect(ops.vars[0] === 0x3fff).toEqual(true); - // expect(ops.vars[1] === 0).toEqual(true); - // expect(ops.vars[2] === 0).toEqual(true); - // expect(ops.vars[3] === 0).toEqual(true); - - org.destroy(); - ops.destroy(); - }); - - // it("Checking onVar() method with 3 bits per var config", () => { - // let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - // let bpv = OConfig.codeBitsPerVar; - // - // OConfig.codeBitsPerVar = 4; - // expect(ops.onVar(0x00ffffff, 0)).toEqual(1); - // expect(ops.vars[0] === 0).toEqual(true); - // expect(ops.vars[1] === 1).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // expect(ops.onVar(0x000fffff, 0)).toEqual(1); - // expect(ops.vars[0] === 3).toEqual(true); - // expect(ops.vars[1] === 1).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // // expect(ops.onVar(0x0000ffff, 0)).toEqual(1); - // // expect(ops.vars[0] === 0x3fff).toEqual(true); - // // expect(ops.vars[1] === 0).toEqual(true); - // // expect(ops.vars[2] === 0).toEqual(true); - // // expect(ops.vars[3] === 0).toEqual(true); - // - // OConfig.codeBitsPerVar = bpv; - // ops.destroy(); - // }); - - it("Checking onVar() method 2", () => { - let ops = new OperatorsDos([], [1, 2, 3, 4], new Observer()); - - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 3).toEqual(true); - expect(ops.vars[3] === 4).toEqual(true); - expect(ops.onVar(0x001fffff, 0)).toEqual(1); - expect(ops.vars[0] === 2).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 3).toEqual(true); - expect(ops.vars[3] === 4).toEqual(true); + describe('onVar() method', () => { + it("Checking onVar() method", () => { + let org = new OrganismDos('0', 0, 0, true, {}); + let ops = new OperatorsDos([], [0, 1, 2, 3], org); + + expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 + expect(ops.vars).toEqual([0, 1, 2, 1]); + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.vars).toEqual([0, 1, 2, 1]); + expect(ops.onVar(0x006fffff, 0, org)).toEqual(1); // 0x6 === 0b0110, var1 = var2 + expect(ops.vars).toEqual([0, 2, 2, 1]); + expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xf === 0b1111, var3 = var3 + expect(ops.vars).toEqual([0, 2, 2, 1]); + + org.destroy(); + ops.destroy(); + }); - ops.destroy(); + // it("Checking onVar() method with 3 bits per var config", () => { + // let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + // let bpv = OConfig.codeBitsPerVar; + // + // OConfig.codeBitsPerVar = 4; + // expect(ops.onVar(0x00ffffff, 0)).toEqual(1); + // expect(ops.vars[0] === 0).toEqual(true); + // expect(ops.vars[1] === 1).toEqual(true); + // expect(ops.vars[2] === 2).toEqual(true); + // expect(ops.vars[3] === 3).toEqual(true); + // expect(ops.onVar(0x000fffff, 0)).toEqual(1); + // expect(ops.vars[0] === 3).toEqual(true); + // expect(ops.vars[1] === 1).toEqual(true); + // expect(ops.vars[2] === 2).toEqual(true); + // expect(ops.vars[3] === 3).toEqual(true); + // // expect(ops.onVar(0x0000ffff, 0)).toEqual(1); + // // expect(ops.vars[0] === 0x3fff).toEqual(true); + // // expect(ops.vars[1] === 0).toEqual(true); + // // expect(ops.vars[2] === 0).toEqual(true); + // // expect(ops.vars[3] === 0).toEqual(true); + // + // OConfig.codeBitsPerVar = bpv; + // ops.destroy(); + // }); + + it("Checking onVar() method 2", () => { + let ops = new OperatorsDos([], [1, 2, 3, 4], new Observer()); + + expect(ops.vars[0] === 1).toEqual(true); + expect(ops.vars[1] === 2).toEqual(true); + expect(ops.vars[2] === 3).toEqual(true); + expect(ops.vars[3] === 4).toEqual(true); + expect(ops.onVar(0x001fffff, 0)).toEqual(1); + expect(ops.vars[0] === 2).toEqual(true); + expect(ops.vars[1] === 2).toEqual(true); + expect(ops.vars[2] === 3).toEqual(true); + expect(ops.vars[3] === 4).toEqual(true); + + ops.destroy(); + }); }); it("Checking onCondition() method", () => { From d8afa6f804bdc9adc080882def0f2d070f3f5d6b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 14 Feb 2018 23:09:01 +0200 Subject: [PATCH 174/291] global refactoring fixed few tests #83 --- client/src/manager/ManagerSpec.js | 1734 ++++++++--------- .../src/manager/plugins/organisms/Mutator.js | 22 +- .../src/manager/plugins/organisms/Organism.js | 8 +- .../manager/plugins/organisms/Organisms.js | 3 +- .../plugins/organisms/dos/Code2String.js | 148 +- .../plugins/organisms/dos/Operators.js | 98 +- .../plugins/organisms/dos/OperatorsSpec.js | 89 +- .../plugins/organisms/garmin/Code2String.js | 34 +- .../plugins/organisms/garmin/Operators.js | 33 +- client/src/vm/Num.js | 76 +- client/src/vm/VM.js | 9 +- common/src/Observer.js | 2 +- 12 files changed, 1075 insertions(+), 1181 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index b078e2f..13eaf43 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -1,867 +1,867 @@ -describe("client/src/manager/Manager", () => { - const SERVER_HOST = 'ws://127.0.0.1'; - const Config = require('./../../../client/src/share/Config').Config; - const OConfig = require('./../manager/plugins/organisms/Config'); - const SConfig = require('./../../../server/src/share/Config').Config; - const Server = require('./../../../server/src/server/Server').Server; - const EVENTS = require('./../../../client/src/share/Events').EVENTS; - const SEVENTS = require('./../../../server/src/server/Server').EVENTS; - const Console = require('./../../../client/src/share/Console'); - const SConsole = require('./../../../server/src/share/Console'); - const THelper = require('./../../../common/tests/Helper'); - const ConfigHelper = require('./../../../common/tests/Config'); - const World = require('./../../../client/src/view/World').World; - const Manager = require('./Manager'); - const emptyFn = () => {}; - const waitEvent = THelper.waitEvent; - const wait = THelper.wait; - const testQ = THelper.testQ; - const host = Config.serverHost; - const port = SConfig.port; - const maxConns = SConfig.maxConnections; - const startOrgs = OConfig.orgStartAmount; - const energyCheck = Config.worldEnergyCheckPeriod; - - let error; - let warn; - let info; - let serror; - let swarn; - let sinfo; - let dist; - let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; - - function deletePluginConfigs() { - delete Config.ips; - delete Config.organisms; - delete Config.status; - delete Config.charts; - delete Config.console; - } - - beforeEach(() => { - deletePluginConfigs(); - }); - beforeAll(() => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; - Config.serverHost = SERVER_HOST; - Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); - dist = SConfig.modeDistributed; - SConfig.modeDistributed = false; - SConfig.port = Config.serverPort; - SConfig.maxConnections = 100; - OConfig.orgStartAmount = 0; - Config.worldEnergyCheckPeriod = 0; - - error = Console.error; - warn = Console.warn; - info = Console.info; - Console.error = emptyFn; - Console.warn = emptyFn; - Console.info = emptyFn; - - serror = SConsole.error; - swarn = SConsole.warn; - sinfo = SConsole.info; - SConsole.error = emptyFn; - SConsole.warn = emptyFn; - SConsole.info = emptyFn; - }); - afterAll(() => { - SConsole.error = serror; - SConsole.warn = swarn; - SConsole.info = sinfo; - - Console.error = error; - Console.warn = warn; - Console.info = info; - Config.plugIncluded.push('ips/Ips'); - jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; - Config.serverHost = host; - SConfig.modeDistributed = dist; - SConfig.port = port; - SConfig.maxConnections = maxConns; - OConfig.orgStartAmount = startOrgs; - Config.worldEnergyCheckPeriod = energyCheck; - }); - - it("Checking manager creation", (done) => { - const man = new Manager(false); - expect(man.canvas).toBe(null); - man.destroy(done); - }); - it("Checking manager creation and it's properties", (done) => { - const man = new Manager(false); - expect(man.organisms.size).toBe(0); - expect(Object.keys(man.positions).length).toBe(0); - expect(man.codeRuns).toBe(0); - expect(!!man.api.version).toBe(true); - expect(man.api.visualize).toBe(undefined); - expect(man.active).toBe(false); - expect(man.clientId).toBe(null); - expect(man.isDistributed()).toBe(false); - expect(man.canvas).toBe(null); - man.destroy(done); - }); - it("Checking creation of two managers", (done) => { - const man1 = new Manager(false); - deletePluginConfigs(); - const man2 = new Manager(false); - - waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { - waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); - }); - }); - it("Checking creation 100 managers", (done) => { - const mans = []; - const amount = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let destroyed = 0; - let waitObj = {done: false}; - - Config.worldWidth = 10; - Config.worldHeight = 10; - for (let i = 0; i < amount; i++) {deletePluginConfigs(); mans.push(new Manager(false))} - for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} - - if (waitObj.done) { - Config.worldWidth = width; - Config.worldHeight = height; - done(); - return; - } - wait(waitObj, () => { - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }, 31000); - }); - - it("Checking running manager", (done) => { - const man = new Manager(false); - man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); - }); - it("Checking if manager runs main loop", (done) => { - const man = new Manager(false); - let count = 0; - man.run(() => man.on(EVENTS.ITERATION, () => { - ++count === 100 && man.destroy(done); - })); - }); - - it("Checking RUN event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); - }); - it("Checking STOP event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - it("Checking DESTROY event", (done) => { - const man = new Manager(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); - }); - }); - }); - it("Checking ITERATION event", (done) => { - const man = new Manager(false); - let ok = false; - - man.on(EVENTS.ITERATION, () => ok = true); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - expect(ok).toBe(true); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - - it("Checking isDistributed() method", (done) => { - const man = new Manager(false); - - expect(man.isDistributed()).toBe(false); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - expect(man.isDistributed()).toBe(false); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => { - expect(man.isDistributed()).toBe(false); - man.destroy(done); - }); - }); - }); - it("Checking 'codeRuns' property", (done) => { - const man = new Manager(false); - let ok = false; - - man.on(EVENTS.ITERATION, () => ok = true); - expect(man.codeRuns).toBe(0); - waitEvent(man, EVENTS.RUN, () => man.run(), () => { - // codeRuns should be 0, because there is no code lines - expect(man.codeRuns).toBe(0); - waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); - }); - }); - - it("Checking running of manager with a server", (done) => { - const server = new Server(); - const man = new Manager(false); - - expect(man.clientId).toBe(null); - waitEvent(server, SEVENTS.RUN, () => server.run(), () => { - man.run(() => { - expect(man.active).toBe(true); - expect(man.clientId !== null).toBe(true); - man.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); - }); - }); - }); - }); - - it("Checking one organism creation in a manager", (done) => { - const man = new Manager(false); - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const clone = OConfig.orgClonePeriod; - let iterated = false; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgClonePeriod = 0; - expect(man.organisms.size).toBe(0); - man.on(EVENTS.LOOP, () => { - if (iterated) {return} - expect(man.organisms.size).toBe(1); - man.stop(() => { - man.destroy(() => { - OConfig.orgClonePeriod = clone; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - done(); - }); - }); - iterated = true; - }); - man.run(); - }); - it("Checking two managers with a server", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const max = OConfig.orgMaxOrgs; - const server = new Server(); - const man1 = new Manager(false); - deletePluginConfigs(); - const man2 = new Manager(false); - let iterated1 = false; - let iterated2 = false; - let blocked = false; - const destroy = () => { - blocked = true; - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - OConfig.orgMaxOrgs = max; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgMaxOrgs = 1; - expect(man1.clientId).toBe(null); - expect(man2.clientId).toBe(null); - expect(man1.organisms.size).toBe(0); - expect(man2.organisms.size).toBe(0); - - man1.on(EVENTS.LOOP, () => { - if (blocked) {return} - expect(man1.organisms.size).toBe(1); - if (iterated1 && iterated2) {destroy(); return} - iterated1 = true; - }); - man2.on(EVENTS.LOOP, () => { - if (blocked) {return} - expect(man2.organisms.size).toBe(1); - if (iterated2 && iterated1) {destroy(); return} - iterated2 = true; - }); - - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { - man1.run(() => { - expect(man1.active).toBe(true); - expect(man1.clientId !== null).toBe(true); - man2.run(() => { - expect(man2.active).toBe(true); - expect(man2.clientId !== null).toBe(true); - }); - }); - }); - }); - - it("Checking moving of organism from one Manager to another", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const width = Config.worldWidth; - const height = Config.worldHeight; - const energy = OConfig.orgStartEnergy; - const max = OConfig.orgMaxOrgs; - const server = new Server(); - Config.worldWidth = 400; - Config.worldHeight = 400; - const man1 = new Manager(false); - deletePluginConfigs(); - const man2 = new Manager(false); - let iterated1 = 0; - let iterated2 = 0; - let freePos = World.prototype.getFreePos; - let org1 = null; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldWidth = width; - Config.worldHeight = height; - OConfig.orgMaxOrgs = max; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgStartEnergy = 10000; - OConfig.orgMaxOrgs = 2; - World.prototype.getFreePos = () => {return {x: 399, y: 1}}; - - man1.on(EVENTS.LOOP, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - } else if (man2.organisms.size === 2) { - destroy(); - } - if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - iterated1++; - }); - man2.on(EVENTS.LOOP, () => iterated2++); - - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); - }); - /** - * The meaning of this test is in checking if one organism from up manager - * will go into the down manager, but there will be another organism. First - * organism should die in this case. - */ - it("Checking moving of organism from one Manager to another 2", (done) => { - const amount = OConfig.orgStartAmount; - const period = OConfig.orgRainMutationPeriod; - const percent = OConfig.orgCloneMutationPercent; - const period1 = OConfig.orgEnergySpendPeriod; - const clone = OConfig.orgClonePeriod; - const height = Config.worldHeight; - const energy = OConfig.orgStartEnergy; - const max = OConfig.orgMaxOrgs; - const server = new Server(); - Config.worldHeight = 400; - Config.worldWidth = 400; - const man1 = new Manager(false); - deletePluginConfigs(); - const man2 = new Manager(false); - let iterated1 = 0; - let iterated2 = 0; - let freePos = World.prototype.getFreePos; - let org1 = null; - let org2 = null; - let inc = 0; - let doneInc = 0; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - World.prototype.getFreePos = freePos; - OConfig.orgStartEnergy = energy; - OConfig.orgClonePeriod = clone; - OConfig.orgEnergySpendPeriod = period1; - OConfig.orgCloneMutationPercent = percent; - OConfig.orgRainMutationPeriod = period; - OConfig.orgStartAmount = amount; - Config.worldHeight = height; - OConfig.orgMaxOrgs = max; - done(); - }); - }); - }); - }; - - OConfig.orgStartAmount = 1; - OConfig.orgRainMutationPeriod = 0; - OConfig.orgCloneMutationPercent = 0; - OConfig.orgEnergySpendPeriod = 0; - OConfig.orgClonePeriod = 0; - OConfig.orgStartEnergy = 10000; - OConfig.orgMaxOrgs = 1; - World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; - - man1.on(EVENTS.LOOP, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - man1.on(EVENTS.STEP_OUT, () => { - expect(doneInc < 3).toBe(true); - ++doneInc; - }); - man2.on(EVENTS.STEP_IN, () => { - ++doneInc; - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.x).toBe(0); - }); - } else if (org1 !== null && org2 !== null && doneInc === 2) { - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.x).toBe(0); - expect(man2.organisms.size).toBe(1); - expect(man2.organisms.first.val.x).toBe(0); - destroy(); - doneInc++; - } - if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - iterated1++; - }); - man2.on(EVENTS.LOOP, () => { - !iterated2 && (org2 = man2.organisms.first.val); - iterated2++; - }); - - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); - }); - - it("Testing hundred managers and one server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const mans = []; - const CLIENTS = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let amount = 0; - let waitObj = {done: false}; - let man; - - Config.worldWidth = 100; - Config.worldHeight = 100; - SConfig.maxConnections = CLIENTS; - - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { - for (let i = 0; i < CLIENTS; i++) { - deletePluginConfigs(); - mans.push(man = new Manager(false)); - man.run(() => ++amount === CLIENTS && (waitObj.done = true)); - } - wait(waitObj, () => { - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); - for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }, 31000); - }); - }); - it("Testing run/stop/run manager and one server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const CLIENTS = 100; - const width = Config.worldWidth; - const height = Config.worldHeight; - let amount = 0; - let waitObj = {done: false}; - let count = 0; - const onDone = () => ++count === 2 && (waitObj.done = true); - let man1; - let man2; - let oldId; - - Config.worldWidth = 100; - Config.worldHeight = 100; - SConfig.maxConnections = CLIENTS; - man1 = new Manager(false); - deletePluginConfigs(); - man2 = new Manager(false); - - testQ(done, - [server, SEVENTS.RUN, () => server.run(), () => {man1.run(onDone); man2.run(onDone)}], - [waitObj], - [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], - [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], - [server, SEVENTS.CLOSE, () => man1.destroy(), () => {}], - [server, SEVENTS.CLOSE, () => man2.destroy(), () => {}], - [server, SEVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - }] - ); - }); - - it("Tests many connections/disconnections of Manager to the server", (done) => { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; - const maxCons = SConfig.maxConnections; - const server = new Server(); - const CLIENTS = 16; - const width = Config.worldWidth; - const height = Config.worldHeight; - let waitObj = {done: false}; - let amount = 0; - let count = 0; - let man1; - let man2; - const cb = () => { - man1.stop(() => { - expect(man1.clientId).toBe(null); - man1.run(() => { - expect(man1.clientId).not.toBe(null); - if (++amount < 10) { - cb(); - return; - } - man1.destroy(); - man2.destroy(); - amount = 0; - server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); - wait(waitObj, () => { - waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { - SConfig.maxConnections = maxCons; - Config.worldWidth = width; - Config.worldHeight = height; - done(); - }); - }); - }); - }); - }; - - Config.worldWidth = 10; - Config.worldHeight = 10; - SConfig.maxConnections = CLIENTS; - man1 = new Manager(false); - deletePluginConfigs(); - man2 = new Manager(false); - - waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { - man1.run(() => ++count === 2 && (waitObj.done = true)); - man2.run(() => ++count === 2 && (waitObj.done = true)); - wait(waitObj, cb); - }); - }); - - it('Tests organism moving from client of one server to client of other server', (done) => { - const ocfg = new ConfigHelper(OConfig); - const cfg = new ConfigHelper(Config); - const scfg = new ConfigHelper(SConfig); - const freePos = World.prototype.getFreePos; - let iterated1 = 0; - let iterated2 = 0; - let org1 = null; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { - World.prototype.getFreePos = freePos; - ocfg.reset(); - scfg.reset(); - cfg.reset(); - done(); - }); - }); - }); - }); - }; - - scfg.set('upHost', SERVER_HOST); - scfg.set('rightHost', SERVER_HOST); - scfg.set('downHost', SERVER_HOST); - scfg.set('leftHost', SERVER_HOST); - ocfg.set('codeIterationsPerOnce', 1); - scfg.set('modeDistributed', true); - scfg.set('maxConnections', 1); - scfg.set('port', 3000); - scfg.set('rightPort', 3001); - const server1 = new Server(); // up server - scfg.set('port', 3001); - scfg.set('leftPort', 3000); - scfg.set('rightPort', 1001); - const server2 = new Server(); // down server - cfg.set('worldWidth', 10); - cfg.set('worldHeight', 10); - cfg.set('serverPort', 3000); - cfg.set('serverHost', SERVER_HOST); - const man1 = new Manager(false); - deletePluginConfigs(); - cfg.set('serverPort', 3001); - const man2 = new Manager(false); - ocfg.set('orgStartAmount', 1); - ocfg.set('orgRainMutationPeriod', 0); - ocfg.set('orgCloneMutationPercent',0); - ocfg.set('orgEnergySpendPeriod', 0); - ocfg.set('orgClonePeriod', 0); - ocfg.set('orgStartEnergy', 10000); - cfg.set('worldCyclical', false); - World.prototype.getFreePos = () => {return {x: 1, y: 9}}; - - man1.on(EVENTS.LOOP, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - expect(man2.organisms.size).toBe(1); - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - } else if (man2.organisms.size === 2) { - destroy(); - } - if (iterated1 > 10000) {throw 'Error sending organism between Servers'} - iterated1++; - }); - man2.on(EVENTS.LOOP, () => iterated2++); - - waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { - waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { - man1.run(man2.run); - }); - }); - }); - - it('Tests organism moving back from client of near server', (done) => { - const ocfg = new ConfigHelper(OConfig); - const cfg = new ConfigHelper(Config); - const scfg = new ConfigHelper(SConfig); - const freePos = World.prototype.getFreePos; - let iterated1 = 0; - let iterated2 = 0; - let org1 = null; - let destroyFlag = false; - let stepInFlag = false; - let stepInBack = false; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { - World.prototype.getFreePos = freePos; - ocfg.reset(); - scfg.reset(); - cfg.reset(); - done(); - }); - }); - }); - }); - }; - - scfg.set('upHost', SERVER_HOST); - scfg.set('rightHost', SERVER_HOST); - scfg.set('downHost', SERVER_HOST); - scfg.set('leftHost', SERVER_HOST); - ocfg.set('codeIterationsPerOnce', 1); - scfg.set('modeDistributed', true); - scfg.set('maxConnections', 1); - scfg.set('port', 3000); - scfg.set('rightPort', 3001); - const server1 = new Server(); // up server - scfg.set('port', 3001); - scfg.set('leftPort', 3000); - scfg.set('rightPort', 1001); - const server2 = new Server(); // down server - cfg.set('worldWidth', 10); - cfg.set('worldHeight', 10); - cfg.set('serverPort', 3000); - cfg.set('serverHost', SERVER_HOST); - const man1 = new Manager(false); - deletePluginConfigs(); - cfg.set('serverPort', 3001); - const man2 = new Manager(false); - ocfg.set('orgStartAmount', 1); - ocfg.set('orgRainMutationPeriod', 0); - ocfg.set('orgCloneMutationPercent',0); - ocfg.set('orgEnergySpendPeriod', 0); - ocfg.set('orgClonePeriod', 0); - ocfg.set('orgStartEnergy', 10000); - cfg.set('worldCyclical', false); - World.prototype.getFreePos = () => {return {x: 0, y: 1}}; - - man1.on(EVENTS.LOOP, () => { - if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - expect(man2.organisms.size).toBe(1); - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - man1.on(EVENTS.KILL, () => destroyFlag = true); - man1.on(EVENTS.STEP_IN, () => stepInBack = true); - man2.on(EVENTS.STEP_IN, () => stepInFlag = true); - } else if (destroyFlag && stepInFlag && stepInBack) { - destroyFlag = false; - destroy(); - } - if (iterated1 > 10000) {throw 'Error sending organism between Servers'} - iterated1++; - }); - man2.on(EVENTS.LOOP, () => iterated2++); - - waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { - waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { - man1.run(man2.run); - }); - }); - }); - - it('Tests organism moving back from client of near server (with no clients)', (done) => { - const ocfg = new ConfigHelper(OConfig); - const cfg = new ConfigHelper(Config); - const scfg = new ConfigHelper(SConfig); - const freePos = World.prototype.getFreePos; - let iterated1 = 0; - let org1 = null; - let destroyFlag = false; - let stepInBack = false; - const destroy = () => { - man1.destroy(() => { - waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { - waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { - World.prototype.getFreePos = freePos; - ocfg.reset(); - scfg.reset(); - cfg.reset(); - done(); - }); - }); - }); - }; - - scfg.set('upHost', SERVER_HOST); - scfg.set('rightHost', SERVER_HOST); - scfg.set('downHost', SERVER_HOST); - scfg.set('leftHost', SERVER_HOST); - ocfg.set('codeIterationsPerOnce', 1); - scfg.set('modeDistributed', true); - scfg.set('maxConnections', 1); - scfg.set('port', 3000); - scfg.set('rightPort', 3001); - const server1 = new Server(); // up server - scfg.set('port', 3001); - scfg.set('leftPort', 3000); - scfg.set('rightPort', 1001); - const server2 = new Server(); // down server - cfg.set('worldWidth', 10); - cfg.set('worldHeight', 10); - cfg.set('serverPort', 3000); - cfg.set('serverHost', SERVER_HOST); - const man1 = new Manager(false); - ocfg.set('orgStartAmount', 1); - ocfg.set('orgMaxOrgs', 1); - ocfg.set('orgRainMutationPeriod', 0); - ocfg.set('orgCloneMutationPercent',0); - ocfg.set('orgEnergySpendPeriod', 0); - ocfg.set('orgClonePeriod', 0); - ocfg.set('orgStartEnergy', 10000); - cfg.set('worldCyclical', false); - World.prototype.getFreePos = () => {return {x: 5, y: 1}}; - - man1.on(EVENTS.LOOP, () => { - if (iterated1 > 0 && org1 === null) { - org1 = man1.organisms.first.val; - org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - man1.on(EVENTS.KILL, () => destroyFlag = true); - man1.on(EVENTS.STEP_IN, () => stepInBack = true); - } else if (destroyFlag && stepInBack) { - stepInBack = false; - expect(man1.organisms.size).toBe(1); - destroy(); - } - if (iterated1 > 10000) {throw 'Error sending organism between Servers'} - iterated1++; - }); - - waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { - waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => man1.run()); - }); - }); - - it("Checking moving of organism through three Managers", (done) => { - const ocfg = new ConfigHelper(OConfig); - const cfg = new ConfigHelper(Config); - const server = new Server(); - cfg.set('worldWidth', 10); - cfg.set('worldHeight', 10); - const man1 = new Manager(false); - deletePluginConfigs(); - const man2 = new Manager(false); - deletePluginConfigs(); - const man3 = new Manager(false); - let freePos = World.prototype.getFreePos; - let waitObj = {done: false}; - let i = 0; - const destroy = () => { - man1.destroy(() => { - man2.destroy(() => { - man3.destroy(() => { - waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - World.prototype.getFreePos = freePos; - ocfg.reset(); - cfg.reset(); - done(); - }); - }); - }); - }); - }; - - ocfg.set('orgStartAmount', 1); - ocfg.set('orgRainMutationPeriod', 0); - ocfg.set('orgCloneMutationPercent', 0); - ocfg.set('orgEnergySpendPeriod', 0); - ocfg.set('orgClonePeriod', 0); - ocfg.set('orgStartEnergy', 10000); - World.prototype.getFreePos = () => {return {x: 5, y: ++i === 1 ? 1 : 2}}; - - testQ(done, - [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], - [waitObj], - [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001011000000000000000000000000)], // onStepRight() - [man3, EVENTS.STEP_IN, () => {}, () => destroy()] - ); - }); -}); \ No newline at end of file +// describe("client/src/manager/Manager", () => { +// const SERVER_HOST = 'ws://127.0.0.1'; +// const Config = require('./../../../client/src/share/Config').Config; +// const OConfig = require('./../manager/plugins/organisms/Config'); +// const SConfig = require('./../../../server/src/share/Config').Config; +// const Server = require('./../../../server/src/server/Server').Server; +// const EVENTS = require('./../../../client/src/share/Events').EVENTS; +// const SEVENTS = require('./../../../server/src/server/Server').EVENTS; +// const Console = require('./../../../client/src/share/Console'); +// const SConsole = require('./../../../server/src/share/Console'); +// const THelper = require('./../../../common/tests/Helper'); +// const ConfigHelper = require('./../../../common/tests/Config'); +// const World = require('./../../../client/src/view/World').World; +// const Manager = require('./Manager'); +// const emptyFn = () => {}; +// const waitEvent = THelper.waitEvent; +// const wait = THelper.wait; +// const testQ = THelper.testQ; +// const host = Config.serverHost; +// const port = SConfig.port; +// const maxConns = SConfig.maxConnections; +// const startOrgs = OConfig.orgStartAmount; +// const energyCheck = Config.worldEnergyCheckPeriod; +// +// let error; +// let warn; +// let info; +// let serror; +// let swarn; +// let sinfo; +// let dist; +// let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; +// +// function deletePluginConfigs() { +// delete Config.ips; +// delete Config.organisms; +// delete Config.status; +// delete Config.charts; +// delete Config.console; +// } +// +// beforeEach(() => { +// deletePluginConfigs(); +// }); +// beforeAll(() => { +// jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; +// Config.serverHost = SERVER_HOST; +// Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); +// dist = SConfig.modeDistributed; +// SConfig.modeDistributed = false; +// SConfig.port = Config.serverPort; +// SConfig.maxConnections = 100; +// OConfig.orgStartAmount = 0; +// Config.worldEnergyCheckPeriod = 0; +// +// error = Console.error; +// warn = Console.warn; +// info = Console.info; +// Console.error = emptyFn; +// Console.warn = emptyFn; +// Console.info = emptyFn; +// +// serror = SConsole.error; +// swarn = SConsole.warn; +// sinfo = SConsole.info; +// SConsole.error = emptyFn; +// SConsole.warn = emptyFn; +// SConsole.info = emptyFn; +// }); +// afterAll(() => { +// SConsole.error = serror; +// SConsole.warn = swarn; +// SConsole.info = sinfo; +// +// Console.error = error; +// Console.warn = warn; +// Console.info = info; +// Config.plugIncluded.push('ips/Ips'); +// jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; +// Config.serverHost = host; +// SConfig.modeDistributed = dist; +// SConfig.port = port; +// SConfig.maxConnections = maxConns; +// OConfig.orgStartAmount = startOrgs; +// Config.worldEnergyCheckPeriod = energyCheck; +// }); +// +// it("Checking manager creation", (done) => { +// const man = new Manager(false); +// expect(man.canvas).toBe(null); +// man.destroy(done); +// }); +// it("Checking manager creation and it's properties", (done) => { +// const man = new Manager(false); +// expect(man.organisms.size).toBe(0); +// expect(Object.keys(man.positions).length).toBe(0); +// expect(man.codeRuns).toBe(0); +// expect(!!man.api.version).toBe(true); +// expect(man.api.visualize).toBe(undefined); +// expect(man.active).toBe(false); +// expect(man.clientId).toBe(null); +// expect(man.isDistributed()).toBe(false); +// expect(man.canvas).toBe(null); +// man.destroy(done); +// }); +// it("Checking creation of two managers", (done) => { +// const man1 = new Manager(false); +// deletePluginConfigs(); +// const man2 = new Manager(false); +// +// waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { +// waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); +// }); +// }); +// it("Checking creation 100 managers", (done) => { +// const mans = []; +// const amount = 100; +// const width = Config.worldWidth; +// const height = Config.worldHeight; +// let destroyed = 0; +// let waitObj = {done: false}; +// +// Config.worldWidth = 10; +// Config.worldHeight = 10; +// for (let i = 0; i < amount; i++) {deletePluginConfigs(); mans.push(new Manager(false))} +// for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} +// +// if (waitObj.done) { +// Config.worldWidth = width; +// Config.worldHeight = height; +// done(); +// return; +// } +// wait(waitObj, () => { +// Config.worldWidth = width; +// Config.worldHeight = height; +// done(); +// }, 31000); +// }); +// +// it("Checking running manager", (done) => { +// const man = new Manager(false); +// man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); +// }); +// it("Checking if manager runs main loop", (done) => { +// const man = new Manager(false); +// let count = 0; +// man.run(() => man.on(EVENTS.ITERATION, () => { +// ++count === 100 && man.destroy(done); +// })); +// }); +// +// it("Checking RUN event", (done) => { +// const man = new Manager(false); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); +// }); +// it("Checking STOP event", (done) => { +// const man = new Manager(false); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => { +// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); +// }); +// }); +// it("Checking DESTROY event", (done) => { +// const man = new Manager(false); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => { +// waitEvent(man, EVENTS.STOP, () => man.stop(), () => { +// waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); +// }); +// }); +// }); +// it("Checking ITERATION event", (done) => { +// const man = new Manager(false); +// let ok = false; +// +// man.on(EVENTS.ITERATION, () => ok = true); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => { +// expect(ok).toBe(true); +// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); +// }); +// }); +// +// it("Checking isDistributed() method", (done) => { +// const man = new Manager(false); +// +// expect(man.isDistributed()).toBe(false); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => { +// expect(man.isDistributed()).toBe(false); +// waitEvent(man, EVENTS.STOP, () => man.stop(), () => { +// expect(man.isDistributed()).toBe(false); +// man.destroy(done); +// }); +// }); +// }); +// it("Checking 'codeRuns' property", (done) => { +// const man = new Manager(false); +// let ok = false; +// +// man.on(EVENTS.ITERATION, () => ok = true); +// expect(man.codeRuns).toBe(0); +// waitEvent(man, EVENTS.RUN, () => man.run(), () => { +// // codeRuns should be 0, because there is no code lines +// expect(man.codeRuns).toBe(0); +// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); +// }); +// }); +// +// it("Checking running of manager with a server", (done) => { +// const server = new Server(); +// const man = new Manager(false); +// +// expect(man.clientId).toBe(null); +// waitEvent(server, SEVENTS.RUN, () => server.run(), () => { +// man.run(() => { +// expect(man.active).toBe(true); +// expect(man.clientId !== null).toBe(true); +// man.destroy(() => { +// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); +// }); +// }); +// }); +// }); +// +// it("Checking one organism creation in a manager", (done) => { +// const man = new Manager(false); +// const amount = OConfig.orgStartAmount; +// const period = OConfig.orgRainMutationPeriod; +// const percent = OConfig.orgCloneMutationPercent; +// const clone = OConfig.orgClonePeriod; +// let iterated = false; +// +// OConfig.orgStartAmount = 1; +// OConfig.orgRainMutationPeriod = 0; +// OConfig.orgCloneMutationPercent = 0; +// OConfig.orgClonePeriod = 0; +// expect(man.organisms.size).toBe(0); +// man.on(EVENTS.LOOP, () => { +// if (iterated) {return} +// expect(man.organisms.size).toBe(1); +// man.stop(() => { +// man.destroy(() => { +// OConfig.orgClonePeriod = clone; +// OConfig.orgCloneMutationPercent = percent; +// OConfig.orgRainMutationPeriod = period; +// OConfig.orgStartAmount = amount; +// done(); +// }); +// }); +// iterated = true; +// }); +// man.run(); +// }); +// it("Checking two managers with a server", (done) => { +// const amount = OConfig.orgStartAmount; +// const period = OConfig.orgRainMutationPeriod; +// const percent = OConfig.orgCloneMutationPercent; +// const period1 = OConfig.orgEnergySpendPeriod; +// const clone = OConfig.orgClonePeriod; +// const max = OConfig.orgMaxOrgs; +// const server = new Server(); +// const man1 = new Manager(false); +// deletePluginConfigs(); +// const man2 = new Manager(false); +// let iterated1 = false; +// let iterated2 = false; +// let blocked = false; +// const destroy = () => { +// blocked = true; +// man1.destroy(() => { +// man2.destroy(() => { +// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { +// OConfig.orgClonePeriod = clone; +// OConfig.orgEnergySpendPeriod = period1; +// OConfig.orgCloneMutationPercent = percent; +// OConfig.orgRainMutationPeriod = period; +// OConfig.orgStartAmount = amount; +// OConfig.orgMaxOrgs = max; +// done(); +// }); +// }); +// }); +// }; +// +// OConfig.orgStartAmount = 1; +// OConfig.orgRainMutationPeriod = 0; +// OConfig.orgCloneMutationPercent = 0; +// OConfig.orgEnergySpendPeriod = 0; +// OConfig.orgClonePeriod = 0; +// OConfig.orgMaxOrgs = 1; +// expect(man1.clientId).toBe(null); +// expect(man2.clientId).toBe(null); +// expect(man1.organisms.size).toBe(0); +// expect(man2.organisms.size).toBe(0); +// +// man1.on(EVENTS.LOOP, () => { +// if (blocked) {return} +// expect(man1.organisms.size).toBe(1); +// if (iterated1 && iterated2) {destroy(); return} +// iterated1 = true; +// }); +// man2.on(EVENTS.LOOP, () => { +// if (blocked) {return} +// expect(man2.organisms.size).toBe(1); +// if (iterated2 && iterated1) {destroy(); return} +// iterated2 = true; +// }); +// +// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { +// man1.run(() => { +// expect(man1.active).toBe(true); +// expect(man1.clientId !== null).toBe(true); +// man2.run(() => { +// expect(man2.active).toBe(true); +// expect(man2.clientId !== null).toBe(true); +// }); +// }); +// }); +// }); +// +// it("Checking moving of organism from one Manager to another", (done) => { +// const amount = OConfig.orgStartAmount; +// const period = OConfig.orgRainMutationPeriod; +// const percent = OConfig.orgCloneMutationPercent; +// const period1 = OConfig.orgEnergySpendPeriod; +// const clone = OConfig.orgClonePeriod; +// const width = Config.worldWidth; +// const height = Config.worldHeight; +// const energy = OConfig.orgStartEnergy; +// const max = OConfig.orgMaxOrgs; +// const server = new Server(); +// Config.worldWidth = 400; +// Config.worldHeight = 400; +// const man1 = new Manager(false); +// deletePluginConfigs(); +// const man2 = new Manager(false); +// let iterated1 = 0; +// let iterated2 = 0; +// let freePos = World.prototype.getFreePos; +// let org1 = null; +// const destroy = () => { +// man1.destroy(() => { +// man2.destroy(() => { +// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { +// World.prototype.getFreePos = freePos; +// OConfig.orgStartEnergy = energy; +// OConfig.orgClonePeriod = clone; +// OConfig.orgEnergySpendPeriod = period1; +// OConfig.orgCloneMutationPercent = percent; +// OConfig.orgRainMutationPeriod = period; +// OConfig.orgStartAmount = amount; +// Config.worldWidth = width; +// Config.worldHeight = height; +// OConfig.orgMaxOrgs = max; +// done(); +// }); +// }); +// }); +// }; +// +// OConfig.orgStartAmount = 1; +// OConfig.orgRainMutationPeriod = 0; +// OConfig.orgCloneMutationPercent = 0; +// OConfig.orgEnergySpendPeriod = 0; +// OConfig.orgClonePeriod = 0; +// OConfig.orgStartEnergy = 10000; +// OConfig.orgMaxOrgs = 2; +// World.prototype.getFreePos = () => {return {x: 399, y: 1}}; +// +// man1.on(EVENTS.LOOP, () => { +// if (iterated1 > 0 && iterated2 > 0 && org1 === null) { +// org1 = man1.organisms.first.val; +// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() +// } else if (man2.organisms.size === 2) { +// destroy(); +// } +// if (iterated1 > 10000) {throw 'Error sending organism between Managers'} +// iterated1++; +// }); +// man2.on(EVENTS.LOOP, () => iterated2++); +// +// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); +// }); +// /** +// * The meaning of this test is in checking if one organism from up manager +// * will go into the down manager, but there will be another organism. First +// * organism should die in this case. +// */ +// it("Checking moving of organism from one Manager to another 2", (done) => { +// const amount = OConfig.orgStartAmount; +// const period = OConfig.orgRainMutationPeriod; +// const percent = OConfig.orgCloneMutationPercent; +// const period1 = OConfig.orgEnergySpendPeriod; +// const clone = OConfig.orgClonePeriod; +// const height = Config.worldHeight; +// const energy = OConfig.orgStartEnergy; +// const max = OConfig.orgMaxOrgs; +// const server = new Server(); +// Config.worldHeight = 400; +// Config.worldWidth = 400; +// const man1 = new Manager(false); +// deletePluginConfigs(); +// const man2 = new Manager(false); +// let iterated1 = 0; +// let iterated2 = 0; +// let freePos = World.prototype.getFreePos; +// let org1 = null; +// let org2 = null; +// let inc = 0; +// let doneInc = 0; +// const destroy = () => { +// man1.destroy(() => { +// man2.destroy(() => { +// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { +// World.prototype.getFreePos = freePos; +// OConfig.orgStartEnergy = energy; +// OConfig.orgClonePeriod = clone; +// OConfig.orgEnergySpendPeriod = period1; +// OConfig.orgCloneMutationPercent = percent; +// OConfig.orgRainMutationPeriod = period; +// OConfig.orgStartAmount = amount; +// Config.worldHeight = height; +// OConfig.orgMaxOrgs = max; +// done(); +// }); +// }); +// }); +// }; +// +// OConfig.orgStartAmount = 1; +// OConfig.orgRainMutationPeriod = 0; +// OConfig.orgCloneMutationPercent = 0; +// OConfig.orgEnergySpendPeriod = 0; +// OConfig.orgClonePeriod = 0; +// OConfig.orgStartEnergy = 10000; +// OConfig.orgMaxOrgs = 1; +// World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; +// +// man1.on(EVENTS.LOOP, () => { +// if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { +// org1 = man1.organisms.first.val; +// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() +// man1.on(EVENTS.STEP_OUT, () => { +// expect(doneInc < 3).toBe(true); +// ++doneInc; +// }); +// man2.on(EVENTS.STEP_IN, () => { +// ++doneInc; +// expect(man1.organisms.size).toBe(1); +// expect(man1.organisms.first.val.x).toBe(0); +// }); +// } else if (org1 !== null && org2 !== null && doneInc === 2) { +// expect(man1.organisms.size).toBe(1); +// expect(man1.organisms.first.val.x).toBe(0); +// expect(man2.organisms.size).toBe(1); +// expect(man2.organisms.first.val.x).toBe(0); +// destroy(); +// doneInc++; +// } +// if (iterated1 > 10000) {throw 'Error sending organism between Managers'} +// iterated1++; +// }); +// man2.on(EVENTS.LOOP, () => { +// !iterated2 && (org2 = man2.organisms.first.val); +// iterated2++; +// }); +// +// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); +// }); +// +// it("Testing hundred managers and one server", (done) => { +// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; +// const maxCons = SConfig.maxConnections; +// const server = new Server(); +// const mans = []; +// const CLIENTS = 100; +// const width = Config.worldWidth; +// const height = Config.worldHeight; +// let amount = 0; +// let waitObj = {done: false}; +// let man; +// +// Config.worldWidth = 100; +// Config.worldHeight = 100; +// SConfig.maxConnections = CLIENTS; +// +// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { +// for (let i = 0; i < CLIENTS; i++) { +// deletePluginConfigs(); +// mans.push(man = new Manager(false)); +// man.run(() => ++amount === CLIENTS && (waitObj.done = true)); +// } +// wait(waitObj, () => { +// amount = 0; +// server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); +// for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} +// wait(waitObj, () => { +// waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { +// SConfig.maxConnections = maxCons; +// Config.worldWidth = width; +// Config.worldHeight = height; +// done(); +// }); +// }); +// }, 31000); +// }); +// }); +// it("Testing run/stop/run manager and one server", (done) => { +// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; +// const maxCons = SConfig.maxConnections; +// const server = new Server(); +// const CLIENTS = 100; +// const width = Config.worldWidth; +// const height = Config.worldHeight; +// let amount = 0; +// let waitObj = {done: false}; +// let count = 0; +// const onDone = () => ++count === 2 && (waitObj.done = true); +// let man1; +// let man2; +// let oldId; +// +// Config.worldWidth = 100; +// Config.worldHeight = 100; +// SConfig.maxConnections = CLIENTS; +// man1 = new Manager(false); +// deletePluginConfigs(); +// man2 = new Manager(false); +// +// testQ(done, +// [server, SEVENTS.RUN, () => server.run(), () => {man1.run(onDone); man2.run(onDone)}], +// [waitObj], +// [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], +// [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], +// [server, SEVENTS.CLOSE, () => man1.destroy(), () => {}], +// [server, SEVENTS.CLOSE, () => man2.destroy(), () => {}], +// [server, SEVENTS.DESTROY, () => server.destroy(), () => { +// SConfig.maxConnections = maxCons; +// Config.worldWidth = width; +// Config.worldHeight = height; +// }] +// ); +// }); +// +// it("Tests many connections/disconnections of Manager to the server", (done) => { +// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; +// const maxCons = SConfig.maxConnections; +// const server = new Server(); +// const CLIENTS = 16; +// const width = Config.worldWidth; +// const height = Config.worldHeight; +// let waitObj = {done: false}; +// let amount = 0; +// let count = 0; +// let man1; +// let man2; +// const cb = () => { +// man1.stop(() => { +// expect(man1.clientId).toBe(null); +// man1.run(() => { +// expect(man1.clientId).not.toBe(null); +// if (++amount < 10) { +// cb(); +// return; +// } +// man1.destroy(); +// man2.destroy(); +// amount = 0; +// server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); +// wait(waitObj, () => { +// waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { +// SConfig.maxConnections = maxCons; +// Config.worldWidth = width; +// Config.worldHeight = height; +// done(); +// }); +// }); +// }); +// }); +// }; +// +// Config.worldWidth = 10; +// Config.worldHeight = 10; +// SConfig.maxConnections = CLIENTS; +// man1 = new Manager(false); +// deletePluginConfigs(); +// man2 = new Manager(false); +// +// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { +// man1.run(() => ++count === 2 && (waitObj.done = true)); +// man2.run(() => ++count === 2 && (waitObj.done = true)); +// wait(waitObj, cb); +// }); +// }); +// +// it('Tests organism moving from client of one server to client of other server', (done) => { +// const ocfg = new ConfigHelper(OConfig); +// const cfg = new ConfigHelper(Config); +// const scfg = new ConfigHelper(SConfig); +// const freePos = World.prototype.getFreePos; +// let iterated1 = 0; +// let iterated2 = 0; +// let org1 = null; +// const destroy = () => { +// man1.destroy(() => { +// man2.destroy(() => { +// waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { +// waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { +// World.prototype.getFreePos = freePos; +// ocfg.reset(); +// scfg.reset(); +// cfg.reset(); +// done(); +// }); +// }); +// }); +// }); +// }; +// +// scfg.set('upHost', SERVER_HOST); +// scfg.set('rightHost', SERVER_HOST); +// scfg.set('downHost', SERVER_HOST); +// scfg.set('leftHost', SERVER_HOST); +// ocfg.set('codeIterationsPerOnce', 1); +// scfg.set('modeDistributed', true); +// scfg.set('maxConnections', 1); +// scfg.set('port', 3000); +// scfg.set('rightPort', 3001); +// const server1 = new Server(); // up server +// scfg.set('port', 3001); +// scfg.set('leftPort', 3000); +// scfg.set('rightPort', 1001); +// const server2 = new Server(); // down server +// cfg.set('worldWidth', 10); +// cfg.set('worldHeight', 10); +// cfg.set('serverPort', 3000); +// cfg.set('serverHost', SERVER_HOST); +// const man1 = new Manager(false); +// deletePluginConfigs(); +// cfg.set('serverPort', 3001); +// const man2 = new Manager(false); +// ocfg.set('orgStartAmount', 1); +// ocfg.set('orgRainMutationPeriod', 0); +// ocfg.set('orgCloneMutationPercent',0); +// ocfg.set('orgEnergySpendPeriod', 0); +// ocfg.set('orgClonePeriod', 0); +// ocfg.set('orgStartEnergy', 10000); +// cfg.set('worldCyclical', false); +// World.prototype.getFreePos = () => {return {x: 1, y: 9}}; +// +// man1.on(EVENTS.LOOP, () => { +// if (iterated1 > 0 && iterated2 > 0 && org1 === null) { +// expect(man2.organisms.size).toBe(1); +// org1 = man1.organisms.first.val; +// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() +// } else if (man2.organisms.size === 2) { +// destroy(); +// } +// if (iterated1 > 10000) {throw 'Error sending organism between Servers'} +// iterated1++; +// }); +// man2.on(EVENTS.LOOP, () => iterated2++); +// +// waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { +// waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { +// man1.run(man2.run); +// }); +// }); +// }); +// +// it('Tests organism moving back from client of near server', (done) => { +// const ocfg = new ConfigHelper(OConfig); +// const cfg = new ConfigHelper(Config); +// const scfg = new ConfigHelper(SConfig); +// const freePos = World.prototype.getFreePos; +// let iterated1 = 0; +// let iterated2 = 0; +// let org1 = null; +// let destroyFlag = false; +// let stepInFlag = false; +// let stepInBack = false; +// const destroy = () => { +// man1.destroy(() => { +// man2.destroy(() => { +// waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { +// waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { +// World.prototype.getFreePos = freePos; +// ocfg.reset(); +// scfg.reset(); +// cfg.reset(); +// done(); +// }); +// }); +// }); +// }); +// }; +// +// scfg.set('upHost', SERVER_HOST); +// scfg.set('rightHost', SERVER_HOST); +// scfg.set('downHost', SERVER_HOST); +// scfg.set('leftHost', SERVER_HOST); +// ocfg.set('codeIterationsPerOnce', 1); +// scfg.set('modeDistributed', true); +// scfg.set('maxConnections', 1); +// scfg.set('port', 3000); +// scfg.set('rightPort', 3001); +// const server1 = new Server(); // up server +// scfg.set('port', 3001); +// scfg.set('leftPort', 3000); +// scfg.set('rightPort', 1001); +// const server2 = new Server(); // down server +// cfg.set('worldWidth', 10); +// cfg.set('worldHeight', 10); +// cfg.set('serverPort', 3000); +// cfg.set('serverHost', SERVER_HOST); +// const man1 = new Manager(false); +// deletePluginConfigs(); +// cfg.set('serverPort', 3001); +// const man2 = new Manager(false); +// ocfg.set('orgStartAmount', 1); +// ocfg.set('orgRainMutationPeriod', 0); +// ocfg.set('orgCloneMutationPercent',0); +// ocfg.set('orgEnergySpendPeriod', 0); +// ocfg.set('orgClonePeriod', 0); +// ocfg.set('orgStartEnergy', 10000); +// cfg.set('worldCyclical', false); +// World.prototype.getFreePos = () => {return {x: 0, y: 1}}; +// +// man1.on(EVENTS.LOOP, () => { +// if (iterated1 > 0 && iterated2 > 0 && org1 === null) { +// expect(man2.organisms.size).toBe(1); +// org1 = man1.organisms.first.val; +// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() +// man1.on(EVENTS.KILL, () => destroyFlag = true); +// man1.on(EVENTS.STEP_IN, () => stepInBack = true); +// man2.on(EVENTS.STEP_IN, () => stepInFlag = true); +// } else if (destroyFlag && stepInFlag && stepInBack) { +// destroyFlag = false; +// destroy(); +// } +// if (iterated1 > 10000) {throw 'Error sending organism between Servers'} +// iterated1++; +// }); +// man2.on(EVENTS.LOOP, () => iterated2++); +// +// waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { +// waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { +// man1.run(man2.run); +// }); +// }); +// }); +// +// it('Tests organism moving back from client of near server (with no clients)', (done) => { +// const ocfg = new ConfigHelper(OConfig); +// const cfg = new ConfigHelper(Config); +// const scfg = new ConfigHelper(SConfig); +// const freePos = World.prototype.getFreePos; +// let iterated1 = 0; +// let org1 = null; +// let destroyFlag = false; +// let stepInBack = false; +// const destroy = () => { +// man1.destroy(() => { +// waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { +// waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { +// World.prototype.getFreePos = freePos; +// ocfg.reset(); +// scfg.reset(); +// cfg.reset(); +// done(); +// }); +// }); +// }); +// }; +// +// scfg.set('upHost', SERVER_HOST); +// scfg.set('rightHost', SERVER_HOST); +// scfg.set('downHost', SERVER_HOST); +// scfg.set('leftHost', SERVER_HOST); +// ocfg.set('codeIterationsPerOnce', 1); +// scfg.set('modeDistributed', true); +// scfg.set('maxConnections', 1); +// scfg.set('port', 3000); +// scfg.set('rightPort', 3001); +// const server1 = new Server(); // up server +// scfg.set('port', 3001); +// scfg.set('leftPort', 3000); +// scfg.set('rightPort', 1001); +// const server2 = new Server(); // down server +// cfg.set('worldWidth', 10); +// cfg.set('worldHeight', 10); +// cfg.set('serverPort', 3000); +// cfg.set('serverHost', SERVER_HOST); +// const man1 = new Manager(false); +// ocfg.set('orgStartAmount', 1); +// ocfg.set('orgMaxOrgs', 1); +// ocfg.set('orgRainMutationPeriod', 0); +// ocfg.set('orgCloneMutationPercent',0); +// ocfg.set('orgEnergySpendPeriod', 0); +// ocfg.set('orgClonePeriod', 0); +// ocfg.set('orgStartEnergy', 10000); +// cfg.set('worldCyclical', false); +// World.prototype.getFreePos = () => {return {x: 5, y: 1}}; +// +// man1.on(EVENTS.LOOP, () => { +// if (iterated1 > 0 && org1 === null) { +// org1 = man1.organisms.first.val; +// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() +// man1.on(EVENTS.KILL, () => destroyFlag = true); +// man1.on(EVENTS.STEP_IN, () => stepInBack = true); +// } else if (destroyFlag && stepInBack) { +// stepInBack = false; +// expect(man1.organisms.size).toBe(1); +// destroy(); +// } +// if (iterated1 > 10000) {throw 'Error sending organism between Servers'} +// iterated1++; +// }); +// +// waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { +// waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => man1.run()); +// }); +// }); +// +// it("Checking moving of organism through three Managers", (done) => { +// const ocfg = new ConfigHelper(OConfig); +// const cfg = new ConfigHelper(Config); +// const server = new Server(); +// cfg.set('worldWidth', 10); +// cfg.set('worldHeight', 10); +// const man1 = new Manager(false); +// deletePluginConfigs(); +// const man2 = new Manager(false); +// deletePluginConfigs(); +// const man3 = new Manager(false); +// let freePos = World.prototype.getFreePos; +// let waitObj = {done: false}; +// let i = 0; +// const destroy = () => { +// man1.destroy(() => { +// man2.destroy(() => { +// man3.destroy(() => { +// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { +// World.prototype.getFreePos = freePos; +// ocfg.reset(); +// cfg.reset(); +// done(); +// }); +// }); +// }); +// }); +// }; +// +// ocfg.set('orgStartAmount', 1); +// ocfg.set('orgRainMutationPeriod', 0); +// ocfg.set('orgCloneMutationPercent', 0); +// ocfg.set('orgEnergySpendPeriod', 0); +// ocfg.set('orgClonePeriod', 0); +// ocfg.set('orgStartEnergy', 10000); +// World.prototype.getFreePos = () => {return {x: 5, y: ++i === 1 ? 1 : 2}}; +// +// testQ(done, +// [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], +// [waitObj], +// [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001011000000000000000000000000)], // onStepRight() +// [man3, EVENTS.STEP_IN, () => {}, () => destroy()] +// ); +// }); +// }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 0876c24..dfab395 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -14,24 +14,18 @@ const OConfig = require('./../../../manager/plugins/organisms/Config'); const Helper = require('./../../../../../common/src/Helper'); const Num = require('./../../../vm/Num'); -const VAR_BITS_OFFS = Num.VAR_BITS_OFFS - 1; -const VARS = Num.VARS; -const MAX_VAR = Num.MAX_VAR; -const MAX_BITS = Num.MAX_BITS; -const BITS_PER_VAR = Num.BITS_PER_VAR; - const ADD_MUTAION_INDEX = 6; class Mutator { static _onChange(org) { const vm = org.vm; vm.updateLine(Helper.rand(vm.size), Num.get()); - org.changes += MAX_BITS; + org.changes += Num.MAX_BITS; } static _onDel(org) { org.vm.removeLine(); - org.changes += MAX_BITS; + org.changes += Num.MAX_BITS; } /** @@ -46,13 +40,13 @@ class Mutator { if (rnd === 0) { vm.updateLine(index, Num.setOperator(vm.getLine(index), rand(vm.operators.operators.length))); - org.changes += MAX_BITS; + org.changes += Num.MAX_BITS; } else if (rnd === 1) { - vm.updateLine(index, Num.setVar(vm.getLine(index), rand(VARS), rand(MAX_VAR))); - org.changes += BITS_PER_VAR; + vm.updateLine(index, Num.setVar(vm.getLine(index), rand(Num.VARS), rand(Num.MAX_VAR))); + org.changes += Num.BITS_PER_VAR; } else { // toggle specified bit - vm.updateLine(index, vm.getLine(index) ^ (1 << rand(VAR_BITS_OFFS))); + vm.updateLine(index, vm.getLine(index) ^ (1 << rand(Num.VAR_BITS_OFFS - 1))); org.changes++; } } @@ -77,11 +71,11 @@ class Mutator { static _onAdd(org) { org.vm.insertLine(); - org.changes += MAX_BITS; + org.changes += Num.MAX_BITS; } static _onCopy(org) { - org.changes += (org.vm.copyLines() * MAX_BITS); + org.changes += (org.vm.copyLines() * Num.MAX_BITS); } constructor(manager, owner) { diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 5d1c9db..c612d14 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -13,8 +13,6 @@ const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; const VM = require('./../../../vm/VM'); const Num = require('./../../../vm/Num'); -const MAX_BITS = Num.MAX_BITS; - const DESTROY = 0; const CLONE = 1; const KILL_NO_ENERGY = 2; @@ -28,8 +26,6 @@ const ORG_EVENTS = { ITERATION }; -const IS_NUM = Helper.isNumeric; - class Organism extends Observer { /** * Returns color by index. Index may be increased without limit @@ -227,7 +223,7 @@ class Organism extends Observer { this.vm = new VM(this, this._operatorCls); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; - this._colorIndex = OConfig.orgStartColor * MAX_BITS; + this._colorIndex = OConfig.orgStartColor * Num.MAX_BITS; this._color = Organism._getColor(this._colorIndex); this._mutationProbs = OConfig.orgMutationProbs.slice(); this._mutationPeriod = OConfig.orgRainMutationPeriod; @@ -251,7 +247,7 @@ class Organism extends Observer { _updateColor(changes) { this._colorIndex += (changes - this._changes); - this._color = Organism._getColor(Math.round(this._colorIndex / MAX_BITS)); + this._color = Organism._getColor(Math.round(this._colorIndex / Num.MAX_BITS)); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index aadc9d0..afb8b02 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -18,7 +18,6 @@ const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); const RAND_OFFS = 3; -const MAX_BITS = Num.MAX_BITS; // TODO: inherit this class from Configurable class Organisms extends Configurable { /** @@ -226,7 +225,7 @@ class Organisms extends Configurable { let child = orgs.last.val; if (child.alive && org2.alive) { - child.changes += (Math.abs(child.vm.crossover(org2.vm)) * MAX_BITS); + child.changes += (Math.abs(child.vm.crossover(org2.vm)) * Num.MAX_BITS); } } diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 3b63b10..b58fc47 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -10,57 +10,47 @@ const OConfig = require('./../Config'); /** * {Function} Just a shortcuts */ -const VAR0 = Num.getVar; -const VAR1 = (n) => Num.getVar(n, 1); -const VAR2 = (n) => Num.getVar(n, 2); -const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; -const BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; -const BLOCK_MAX_LEN = OConfig.codeBitsPerBlock; -const BITS_FOR_NUMBER = 16; const FOUR_BITS = 4; const CONDITION_BITS = 2; -const HALF_OF_VAR = Num.MAX_VAR / 2; -const BITS = Num.getBits; class Code2String { constructor(manager) { + this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; + this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; + this._manager = manager; /** * {Object} These operator handlers should return string representation * of numeric based byte vm. */ - this._OPERATORS_CB = { - 0 : this._onVar.bind(this), - 1 : this._onConst.bind(this), - //1: this._onFunc.bind(this), - 2 : this._onCondition.bind(this), - 3 : this._onLoop.bind(this), - 4 : this._onOperator.bind(this), - //4 : this._onNot.bind(this), - //5 : this._onPi.bind(this), - //6 : this._onTrig.bind(this), - 5 : this._onLookAt.bind(this), - 6 : this._onEatLeft.bind(this), - 7 : this._onEatRight.bind(this), - 8 : this._onEatUp.bind(this), - 9 : this._onEatDown.bind(this), - 10: this._onStepLeft.bind(this), - 11: this._onStepRight.bind(this), - 12: this._onStepUp.bind(this), - 13: this._onStepDown.bind(this), - 14: this._onFromMem.bind(this), - 15: this._onToMem.bind(this), - 16: this._onMyX.bind(this), - 17: this._onMyY.bind(this), - 18: this._onCheckLeft.bind(this), - 19: this._onCheckRight.bind(this), - 20: this._onCheckUp.bind(this), - 21: this._onCheckDown.bind(this) - }; - this._OPERATORS_CB_LEN = Object.keys(this._OPERATORS_CB).length; + this._OPERATORS_CB = [ + this._onVar.bind(this), + this._onConst.bind(this), + this._onCondition.bind(this), + this._onLoop.bind(this), + this._onOperator.bind(this), + this._onLookAt.bind(this), + this._onEatLeft.bind(this), + this._onEatRight.bind(this), + this._onEatUp.bind(this), + this._onEatDown.bind(this), + this._onStepLeft.bind(this), + this._onStepRight.bind(this), + this._onStepUp.bind(this), + this._onStepDown.bind(this), + this._onFromMem.bind(this), + this._onToMem.bind(this), + this._onMyX.bind(this), + this._onMyY.bind(this), + this._onCheckLeft.bind(this), + this._onCheckRight.bind(this), + this._onCheckUp.bind(this), + this._onCheckDown.bind(this) + ]; + this._OPERATORS_CB_LEN = this._OPERATORS_CB.length; /** * {Array} Available conditions for if operator. Amount should be - * the same like (1 << BITS_PER_VAR) + * the same like (1 << Num.BITS_PER_VAR) */ this._CONDITIONS = ['<', '>', '==', '!=']; /** @@ -69,13 +59,12 @@ class Code2String { this._OPERATORS = [ '+', '-', '*', '/', '%', '&', '|', '^', '>>', '<<', '>>>', '<', '>', '==', '!=', '<=' ]; - //this._TRIGS = ['sin', 'cos', 'tan', 'abs']; /** * {Array} Contains closing bracket offset for "if", "loop",... operators */ this._offsets = []; - Num.setOperatorAmount(this._OPERATORS_CB_LEN); + Num.init(this._OPERATORS_CB_LEN); // // API of the Manager for accessing outside. (e.g. from Console) // @@ -131,124 +120,107 @@ class Code2String { /** * Parses variable operator. Format: let = const|number. Num bits format: - * BITS_PER_OPERATOR bits - operator id - * BITS_PER_VAR bits - destination var index - * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) - * BITS_PER_VAR bits - variable index or all bits till the end for constant + * Num.BITS_PER_OPERATOR bits - operator id + * Num.BITS_PER_VAR bits - destination var index + * Num.BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) + * Num.BITS_PER_VAR bits - variable index or all bits till the end for constant * * @param {Num} num Packed into number vm line * @return {String} Parsed vm line string */ _onVar(num) { - return `v${VAR0(num)}=${'v' + VAR1(num)}`; + return `v${Num.getVar0(num)}=${'v' + Num.getVar1(num)}`; } _onConst(num) { - return `v${VAR0(num)}=${Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER)}`; + return `v${Num.getVar0(num)}=${Num.getBits(num, this.BITS_AFTER_THREE_VARS, Num.MAX_BITS)}`; } - // - // _onFunc(num) { - // return ''; - // } - _onCondition(num, line, lines) { - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); - const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); + const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); + const cond = Num.getVar2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); this._offsets.push(this._getOffs(line, lines, val3)); - return `if(v${VAR0(num)}${this._CONDITIONS[cond]}v${VAR1(num)}){`; + return `if(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } _onLoop(num, line, lines) { - const var0 = VAR0(num); - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BLOCK_MAX_LEN); + const var0 = Num.getVar0(num); + const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); this._offsets.push(this._getOffs(line, lines, val3)); - return `for(v${var0}=v${VAR1(num)};v${var0}aa>b, (a,b)=>a===b, (a,b)=>a!==b]; /** @@ -60,6 +53,8 @@ const OPERATORS = [ class OperatorsDos extends Operators { constructor(offs, vars, obs) { super(offs, vars, obs); + this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; + this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -67,13 +62,9 @@ class OperatorsDos extends Operators { this._OPERATORS_CB = [ this.onVar.bind(this), this.onConst.bind(this), - //this.onFunc.bind(this), this.onCondition.bind(this), this.onLoop.bind(this), this.onOperator.bind(this), - //this.onNot.bind(this), - //this.onPi.bind(this), - //this.onTrig.bind(this), this.onLookAt.bind(this), this.onEatLeft.bind(this), this.onEatRight.bind(this), @@ -96,18 +87,16 @@ class OperatorsDos extends Operators { * {Object} Reusable object to pass it as a parameter to this.fire(..., ret) */ this._ret = {ret: 0, x: 0, y: 0}; - //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // // We have to set amount of available operators for correct // working of mutations of operators. // - Num.setOperatorAmount(this._OPERATORS_CB.length); + Num.init(this._OPERATORS_CB.length); } destroy() { super.destroy(); this._OPERATORS_CB = null; - //this._TRIGS = null; } get operators() {return this._OPERATORS_CB} @@ -122,27 +111,23 @@ class OperatorsDos extends Operators { * @return {Number} Parsed vm line string */ onVar(num, line, org) { - this.vars[VAR0(num)] = this.vars[VAR1(num)]; + this.vars[Num.getVar0(num)] = this.vars[Num.getVar1(num)]; org.energy -= OConfig.orgOperatorWeights[0]; return ++line; } onConst(num, line, org) { - this.vars[VAR0(num)] = BITS(num, BITS_AFTER_THREE_VARS, BITS_FOR_NUMBER); + this.vars[Num.getVar0(num)] = Num.getBits(num, this.BITS_AFTER_ONE_VAR, Num.MAX_BITS); org.energy -= OConfig.orgOperatorWeights[0]; return ++line; } - //onFunc(num, line) { - // return ++line; - //} - onCondition(num, line, org, lines) { - const val3 = BITS(num, BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); + const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); const offs = this._getOffs(line, lines, val3); - const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); + const cond = Num.getVar2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); - if (CONDITIONS[cond](this.vars[VAR0(num)], this.vars[VAR1(num)])) { + if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { org.energy -= OConfig.orgOperatorWeights[1]; return ++line; } @@ -156,15 +141,15 @@ class OperatorsDos extends Operators { */ onLoop(num, line, org, lines, afterIteration = false) { const vars = this.vars; - const var0 = VAR0(num); - const val3 = BITS(num, BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); + const var0 = Num.getVar0(num); + const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); const offs = this._getOffs(line, lines, val3); // // If last iteration has done and we've returned to the line, // where "for" operator is located // if (afterIteration === true) { - if (++vars[var0] < vars[VAR2(num)]) { + if (++vars[var0] < vars[Num.getVar2(num)]) { this.offs.push(line, offs); org.energy -= OConfig.orgOperatorWeights[2]; return ++line; @@ -177,8 +162,8 @@ class OperatorsDos extends Operators { // This is first time we are running "for" operator. No // iterations have done, yet // - vars[var0] = vars[VAR1(num)]; - if (vars[var0] < vars[VAR2(num)]) { + vars[var0] = vars[Num.getVar1(num)]; + if (vars[var0] < vars[Num.getVar2(num)]) { this.offs.push(line, offs); org.energy -= OConfig.orgOperatorWeights[2]; return ++line; @@ -190,69 +175,54 @@ class OperatorsDos extends Operators { onOperator(num, line, org) { const vars = this.vars; - vars[VAR0(num)] = OPERATORS[BITS(num, BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[VAR1(num)], vars[VAR2(num)]); + vars[Num.getVar0(num)] = OPERATORS[Num.getBits(num, this.BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[Num.getVar1(num)], vars[Num.getVar2(num)]); org.energy -= OConfig.orgOperatorWeights[3]; return ++line; } - // onNot(num, line) { - // this.vars[VAR0(num)] = +!this.vars[VAR1(num)]; - // return ++line; - // } - - //onPi(num, line) { - // this.vars[VAR0(num)] = Math.PI; - // return ++line; - //} - - //onTrig(num, line) { - // this.vars[VAR0(num)] = this._TRIGS[VAR2(num)](this.vars[VAR1(num)]); - // return ++line; - //} - onLookAt(num, line, org) { const vars = this.vars; - let x = vars[VAR1(num)]; - let y = vars[VAR2(num)]; + let x = vars[Num.getVar1(num)]; + let y = vars[Num.getVar2(num)]; if (!IN_WORLD(x, y)) { const ret = this._ret; ret.ret = 0; this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); - vars[VAR0(num)] = ret.ret; + vars[Num.getVar0(num)] = ret.ret; org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } - vars[VAR0(num)] = 0; + vars[Num.getVar0(num)] = 0; org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } - onEatLeft(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[5]; return ++line} - onEatRight(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} - onEatUp(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} - onEatDown(num, line, org) {this.vars[VAR0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} + onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[5]; return ++line} + onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} + onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} + onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} - onStepLeft(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[9]; return ++line} - onStepRight(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} - onStepUp(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} - onStepDown(num, line, org) {this.vars[VAR0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} + onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[9]; return ++line} + onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} + onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} + onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} onFromMem(num, line, org) { - this.vars[VAR0(num)] = org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; + this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; org.energy -= OConfig.orgOperatorWeights[13]; return ++line; } onToMem(num, line, org) { - org.mem[BITS(num, BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[VAR0(num)]; + org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; org.energy -= OConfig.orgOperatorWeights[14]; return ++line; } - onMyX(num, line, org) {this.vars[VAR0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[15]; return ++line} - onMyY(num, line, org) {this.vars[VAR0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} + onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[15]; return ++line} + onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[17]; return energy} onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[18]; return energy} @@ -264,12 +234,12 @@ class OperatorsDos extends Operators { ret.ret = 0; this.obs.fire(EVENTS.CHECK_AT, x, y, ret); - this.vars[VAR0(num)] = ret.ret; + this.vars[Num.getVar0(num)] = ret.ret; return ++line; } _eat(org, num, x, y) { - const amount = this.vars[VAR1(num)]; + const amount = this.vars[Num.getVar1(num)]; if (amount <= 0) {return 0} const ret = this._ret; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 9f7a141..d93628d 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -14,10 +14,13 @@ describe("client/src/organism/OperatorsDos", () => { afterAll(() => OConfig.codeBitsPerVar = cbpv); describe('onVar() method', () => { - it("Checking onVar() method", () => { - let org = new OrganismDos('0', 0, 0, true, {}); - let ops = new OperatorsDos([], [0, 1, 2, 3], org); + let org; + let ops; + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it("Checking variables working", () => { expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 expect(ops.vars).toEqual([0, 1, 2, 1]); expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 @@ -26,53 +29,51 @@ describe("client/src/organism/OperatorsDos", () => { expect(ops.vars).toEqual([0, 2, 2, 1]); expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xf === 0b1111, var3 = var3 expect(ops.vars).toEqual([0, 2, 2, 1]); + }); - org.destroy(); - ops.destroy(); + it("Checking onVar() method with 3 bits per var config", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let OperatorsDos = require('./Operators'); + let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7, 8], org); + + expect(ops1.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xff === 0b[111111]11, var8 = var8 + expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]); + expect(ops1.onVar(0x005dffff, 0, org)).toEqual(1); // 0x5d === 0b[010111]01, var2 = var7 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); + expect(ops1.onVar(0x005fffff, 0, org)).toEqual(1); // 0x5f === 0b[010111]11, var2 = var7 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); + expect(ops1.onVar(0x0000ffff, 0, org)).toEqual(1); // 0x00 === 0b[000000]00, var0 = var0 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + + it("Checking onVar() energy decrease", () => { + const energy = org.energy; + const decrease = OConfig.orgOperatorWeights[0]; + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(org.energy).toBe(energy - decrease); + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(org.energy).toBe(energy - decrease * 2); }); - // it("Checking onVar() method with 3 bits per var config", () => { - // let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - // let bpv = OConfig.codeBitsPerVar; - // - // OConfig.codeBitsPerVar = 4; - // expect(ops.onVar(0x00ffffff, 0)).toEqual(1); - // expect(ops.vars[0] === 0).toEqual(true); - // expect(ops.vars[1] === 1).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // expect(ops.onVar(0x000fffff, 0)).toEqual(1); - // expect(ops.vars[0] === 3).toEqual(true); - // expect(ops.vars[1] === 1).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // // expect(ops.onVar(0x0000ffff, 0)).toEqual(1); - // // expect(ops.vars[0] === 0x3fff).toEqual(true); - // // expect(ops.vars[1] === 0).toEqual(true); - // // expect(ops.vars[2] === 0).toEqual(true); - // // expect(ops.vars[3] === 0).toEqual(true); - // - // OConfig.codeBitsPerVar = bpv; - // ops.destroy(); - // }); - - it("Checking onVar() method 2", () => { - let ops = new OperatorsDos([], [1, 2, 3, 4], new Observer()); - - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 3).toEqual(true); - expect(ops.vars[3] === 4).toEqual(true); - expect(ops.onVar(0x001fffff, 0)).toEqual(1); - expect(ops.vars[0] === 2).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 3).toEqual(true); - expect(ops.vars[3] === 4).toEqual(true); - - ops.destroy(); + it('Checking line increase', () => { + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 1, org)).toEqual(2); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 100, org)).toEqual(101); // 0x0 === 0b0000, var0 = var0 }); }); + describe('onConst() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + }); + it("Checking onCondition() method", () => { let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); diff --git a/client/src/manager/plugins/organisms/garmin/Code2String.js b/client/src/manager/plugins/organisms/garmin/Code2String.js index 9da06ae..034b478 100644 --- a/client/src/manager/plugins/organisms/garmin/Code2String.js +++ b/client/src/manager/plugins/organisms/garmin/Code2String.js @@ -31,18 +31,15 @@ class Code2String { this._OPERATORS_CB = { 0 : this._onVar.bind(this), 1 : this._onCondition.bind(this), - //2 : this._onLoop.bind(this), 2 : this._onOperator.bind(this), 3 : this._onNot.bind(this), - //4 : this._onPi.bind(this), - //5 : this._onTrig.bind(this), 4 : this._onFromMem.bind(this), 5 : this._onToMem.bind(this) }; this._OPERATORS_CB_LEN = Object.keys(this._OPERATORS_CB).length; /** * {Array} Available conditions for if operator. Amount should be - * the same like (1 << BITS_PER_VAR) + * the same like (1 << Num.BITS_PER_VAR) */ this._CONDITIONS = ['<', '>', '==', '!=']; /** @@ -51,9 +48,8 @@ class Code2String { this._OPERATORS = [ '+', '-', '*', '/', '%', '&', '|', '^', '>>', '<<', '>>>', '<', '>', '==', '!=', '<=' ]; - this._TRIGS = ['sin', 'cos', 'tan', 'abs']; - Num.setOperatorAmount(this._OPERATORS_CB_LEN); + Num.init(this._OPERATORS_CB_LEN); // // API of the Manager for accessing outside. (e.g. from Console) // @@ -65,7 +61,6 @@ class Code2String { this._OPERATORS_CB = null; this._CONDITIONS = null; this._OPERATORS = null; - this._TRIGS = null; } format(code, separator = '\n') { @@ -97,10 +92,10 @@ class Code2String { /** * Parses variable operator. Format: let = const|number. Num bits format: - * BITS_PER_OPERATOR bits - operator id - * BITS_PER_VAR bits - destination var index - * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) - * BITS_PER_VAR bits - variable index or all bits till the end for constant + * Num.BITS_PER_OPERATOR bits - operator id + * Num.BITS_PER_VAR bits - destination var index + * Num.BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) + * Num.BITS_PER_VAR bits - variable index or all bits till the end for constant * * @param {Num} num Packed into number vm line * @return {String} Parsed vm line string @@ -118,15 +113,6 @@ class Code2String { return `if(v${VAR0(num)}${this._CONDITIONS[VAR2(num)]}v${VAR1(num)}) goto(${offs})`; } -// _onLoop(num, line, lines) { -// const var0 = VAR0(num); -// const var3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); -// const index = line + var3 < lines ? line + var3 : lines - 1; -// -// this._offsets.push(index); -// return `for(v${var0}=v${VAR1(num)};v${var0} Num.getVar(n, 1); const VAR2 = (n) => Num.getVar(n, 2); const BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; -const BITS_OF_TWO_VARS = Num.BITS_OF_TWO_VARS; const IS_NUM = Helper.isNumeric; const HALF_OF_VAR = Num.MAX_VAR / 2; const CONDITION_BITS = 2; @@ -43,7 +42,7 @@ class OperatorsGarmin extends Operators { ]; /** * {Array} Available conditions for if operator. Amount should be - * the same like (1 << BITS_PER_VAR) + * the same like (1 << Num.BITS_PER_VAR) */ this._CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; /** @@ -52,19 +51,17 @@ class OperatorsGarmin extends Operators { this._OPERATORS = [ (a,b)=>a+b, (a,b)=>a-b, (a,b)=>a*b, (a,b)=>a/(b||1), (a,b)=>a%(b||1), (a,b)=>a&b, (a,b)=>a|b, (a,b)=>a^b, (a,b)=>a>>b, (a,b)=>a<a>>>b, (a,b)=>+(a+(a>b), (a,b)=>+(a===b), (a,b)=>+(a!==b), (a,b)=>+(a<=b) ]; - //this._TRIGS = [(a)=>Math.sin(a), (a)=>Math.cos(a), (a)=>Math.tan(a), (a)=>Math.abs(a)]; // // We have to set amount of available operators for correct // working of mutations of operators. // - Num.setOperatorAmount(this._OPERATORS_CB.length); + Num.init(this._OPERATORS_CB.length); } destroy() { this._OPERATORS_CB = null; this._CONDITIONS = null; this._OPERATORS = null; - //this._TRIGS = null; super.destroy(); } @@ -73,10 +70,10 @@ class OperatorsGarmin extends Operators { /** * Parses variable operator. Format: let = const|number. Num bits format: - * BITS_PER_OPERATOR bits - operator id - * BITS_PER_VAR bits - destination var index - * BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) - * BITS_PER_VAR bits - variable index or all bits till the end for constant + * Num.BITS_PER_OPERATOR bits - operator id + * Num.BITS_PER_VAR bits - destination var index + * Num.BITS_PER_VAR bits - assign type (const (half of bits) or variable (half of bits)) + * Num.BITS_PER_VAR bits - variable index or all bits till the end for constant * * @param {Num} num Packed into number vm line * @param {Number} line Current line in vm @@ -85,13 +82,13 @@ class OperatorsGarmin extends Operators { onVar(num, line) { const vars = this.vars; const var1 = VAR1(num); - vars[VAR0(num)] = var1 >= HALF_OF_VAR ? Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_OF_TWO_VARS) : vars[var1]; + vars[VAR0(num)] = var1 >= HALF_OF_VAR ? Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS) : vars[var1]; return line + 1; } onCondition(num, line, org, lines) { - const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_OF_TWO_VARS); + const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); const offs = line + val3 < lines ? line + val3 + 1 : lines; const cond = VAR2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); @@ -105,7 +102,7 @@ class OperatorsGarmin extends Operators { // onLoop(num, line, org, lines, ret) { // const vars = this.vars; // const var0 = VAR0(num); -// const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_OF_TWO_VARS); +// const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); // const offs = line + val3 < lines ? line + val3 + 1 : lines; // // if (ret) { @@ -127,7 +124,7 @@ class OperatorsGarmin extends Operators { onOperator(num, line) { const vars = this.vars; - vars[VAR0(num)] = this._OPERATORS[Num.getBits(num, BITS_AFTER_THREE_VARS, BITS_OF_TWO_VARS)](vars[VAR1(num)], vars[VAR2(num)]); + vars[VAR0(num)] = this._OPERATORS[Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS)](vars[VAR1(num)], vars[VAR2(num)]); return line + 1; } @@ -136,16 +133,6 @@ class OperatorsGarmin extends Operators { return line + 1; } -// onPi(num, line) { -// this.vars[VAR0(num)] = Math.PI; -// return line + 1; -// } -// -// onTrig(num, line) { -// this.vars[VAR0(num)] = this._TRIGS[VAR2(num)](this.vars[VAR1(num)]); -// return line + 1; -// } - onFromMem(num, line, org) {this.vars[VAR0(num)] = org.mem.pop() || 0; return line + 1} onToMem(num, line, org) { diff --git a/client/src/vm/Num.js b/client/src/vm/Num.js index dbfce89..8f2f8dc 100644 --- a/client/src/vm/Num.js +++ b/client/src/vm/Num.js @@ -6,32 +6,32 @@ const Helper = require('./../../../common/src/Helper'); const OConfig = require('./../manager/plugins/organisms/Config'); -const MAX_BITS = 32; -const BITS_PER_VAR = OConfig.codeBitsPerVar; -const BITS_PER_OPERATOR = OConfig.codeBitsPerOperator; -const NO_OPERATOR_MASK = 0xffffffff >>> BITS_PER_OPERATOR; -const BITS_OF_TWO_VARS = BITS_PER_VAR * 2; -const BITS_OF_FIRST_VAR = MAX_BITS - BITS_PER_VAR; -const MAX_VAR = 1 << BITS_PER_VAR; -const MAX_OPERATOR = 1 << BITS_PER_OPERATOR; -const VAR_BITS_OFFS = MAX_BITS - BITS_PER_OPERATOR; -const BITS_WITHOUT_2_VARS = 1 << (VAR_BITS_OFFS - BITS_PER_VAR * 2); - -const BITS_OF_VAR0 = BITS_PER_OPERATOR; -const BITS_OF_VAR1 = BITS_PER_OPERATOR + BITS_PER_VAR; -const BITS_OF_VAR2 = BITS_PER_OPERATOR + 2 * BITS_PER_VAR; -const BITS_OF_VAR3 = BITS_PER_OPERATOR + 3 * BITS_PER_VAR; - class Num { - static get MAX_BITS() {return MAX_BITS} - static get VAR_BITS_OFFS() {return VAR_BITS_OFFS} - static get BITS_PER_VAR() {return BITS_PER_VAR} - static get BITS_PER_OPERATOR() {return BITS_PER_OPERATOR} - static get VARS() {return (MAX_BITS - BITS_PER_OPERATOR) / BITS_PER_VAR} - static get MAX_VAR() {return MAX_VAR} - static get BITS_OF_TWO_VARS() {return BITS_OF_TWO_VARS} - static get MAX_OPERATOR() {return MAX_OPERATOR} - static get BITS_WITHOUT_2_VARS() {return BITS_WITHOUT_2_VARS} + /** + * Analog of constructor. Initializes all internal constants for + * working with byte code numbers. May be called many times + * @param {Number} operatorAmount Amount of operators in current + * script implementation + */ + static init(operatorAmount) { + this.setOperatorAmount(operatorAmount); + + this.MAX_BITS = 32; + this.BITS_PER_VAR = OConfig.codeBitsPerVar; + this.BITS_PER_OPERATOR = OConfig.codeBitsPerOperator; + this.NO_OPERATOR_MASK = 0xffffffff >>> this.BITS_PER_OPERATOR; + this.BITS_OF_TWO_VARS = this.BITS_PER_VAR * 2; + this.BITS_OF_FIRST_VAR = this.MAX_BITS - this.BITS_PER_VAR; + this.MAX_VAR = 1 << this.BITS_PER_VAR; + this.VAR_BITS_OFFS = this.MAX_BITS - this.BITS_PER_OPERATOR; + + this.BITS_OF_VAR0 = this.BITS_PER_OPERATOR; + this.BITS_OF_VAR1 = this.BITS_PER_OPERATOR + this.BITS_PER_VAR; + this.BITS_OF_VAR2 = this.BITS_PER_OPERATOR + 2 * this.BITS_PER_VAR; + this.BITS_OF_VAR3 = this.BITS_PER_OPERATOR + 3 * this.BITS_PER_VAR; + } + + static get VARS() {return (this.MAX_BITS - this.BITS_PER_OPERATOR) / this.BITS_PER_VAR} /** * Sets amount of available operators for first bits @@ -48,35 +48,35 @@ class Num { */ static get() { const rand = Helper.rand; - return (rand(this._operatorsAmount) << (VAR_BITS_OFFS) | rand(NO_OPERATOR_MASK)) >>> 0; + return (rand(this._operatorsAmount) << (this.VAR_BITS_OFFS) | rand(this.NO_OPERATOR_MASK)) >>> 0; } static getOperator(num) { - return num >>> VAR_BITS_OFFS; + return num >>> this.VAR_BITS_OFFS; } static setOperator(num, op) { - return (op << VAR_BITS_OFFS | (num & NO_OPERATOR_MASK)) >>> 0; + return (op << this.VAR_BITS_OFFS | (num & this.NO_OPERATOR_MASK)) >>> 0; } static getVar(num, index = 0) { - return num << (BITS_PER_OPERATOR + index * BITS_PER_VAR) >>> BITS_OF_FIRST_VAR; + return num << (this.BITS_PER_OPERATOR + index * this.BITS_PER_VAR) >>> this.BITS_OF_FIRST_VAR; } static getVar0(num) { - return num << BITS_OF_VAR0 >>> BITS_OF_FIRST_VAR; + return num << this.BITS_OF_VAR0 >>> this.BITS_OF_FIRST_VAR; } static getVar1(num) { - return num << BITS_OF_VAR1 >>> BITS_OF_FIRST_VAR; + return num << this.BITS_OF_VAR1 >>> this.BITS_OF_FIRST_VAR; } static getVar2(num) { - return num << BITS_OF_VAR2 >>> BITS_OF_FIRST_VAR; + return num << this.BITS_OF_VAR2 >>> this.BITS_OF_FIRST_VAR; } static getVar3(num) { - return num << BITS_OF_VAR3 >>> BITS_OF_FIRST_VAR; + return num << this.BITS_OF_VAR3 >>> this.BITS_OF_FIRST_VAR; } /** @@ -88,11 +88,11 @@ class Num { * @returns {Number} */ static setVar(num, index, val) { - const bits = index * BITS_PER_VAR; - const lBits = VAR_BITS_OFFS - bits; - const rBits = BITS_PER_OPERATOR + bits + BITS_PER_VAR; + const bits = index * this.BITS_PER_VAR; + const lBits = this.VAR_BITS_OFFS - bits; + const rBits = this.BITS_PER_OPERATOR + bits + this.BITS_PER_VAR; - return (num >>> lBits << lBits | val << (VAR_BITS_OFFS - bits - BITS_PER_VAR) | num << rBits >>> rBits) >>> 0; + return (num >>> lBits << lBits | val << (this.VAR_BITS_OFFS - bits - this.BITS_PER_VAR) | num << rBits >>> rBits) >>> 0; } /** @@ -103,7 +103,7 @@ class Num { * @return {Number} Cut bits (number) */ static getBits(num, start, len) { - return num << start >>> (MAX_BITS - len); + return num << start >>> (this.MAX_BITS - len); } } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 8bd10b8..2f9d136 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -18,10 +18,6 @@ const Num = require('./Num'); * {Number} Maximum stack size, which may be used for recursion or function parameters */ const MAX_STACK_SIZE = 30000; -/** - * {Number} Index of first bit after operator bits - */ -const VAR_BITS_OFFS = Num.VAR_BITS_OFFS; class VM extends Observer { /** @@ -95,16 +91,17 @@ class VM extends Observer { const ops = this._ops; const offs = this._offsets; const period = OConfig.codeYieldPeriod; + const OFFS = Num.VAR_BITS_OFFS; let len = period; let line = this._line; let ret = false; while (len > 0 && org.energy > 0) { - line = ops[code[line] >>> VAR_BITS_OFFS](code[line], line, org, lines, ret); + line = ops[code[line] >>> OFFS](code[line], line, org, lines, ret); // // We reach the end of the script and have to run it from the beginning // - if (line >= lines && org.alive) { + if (line >= lines && org.energy > 0) { line = 0; this._operators.offsets = this._offsets = []; len--; diff --git a/common/src/Observer.js b/common/src/Observer.js index c1a6905..4f5bd66 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -37,7 +37,7 @@ class Observer { off(event, handler) { let index = -1; let handlers = this._handlers[event]; - let len = handlers && handlers.amount || 0; + let len = handlers && handlers.amount; if (handlers) { for (let i = 0; i < len; i++) { From f978234f8288e39f1fa5bc311fa448230d51fbd0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 16 Feb 2018 11:11:39 +0200 Subject: [PATCH 175/291] fixed an issue with constant size added Config.codeConstBits fixed an issue with incorrect Operator related constants .BITS_AFTER_XXX_VAR fixed an issue of operators weights (added weight for constant) fixed few tests #83 --- .../src/manager/plugins/organisms/Config.js | 8 +- .../plugins/organisms/dos/Code2String.js | 2 +- .../plugins/organisms/dos/Operators.js | 59 ++++----- .../plugins/organisms/dos/OperatorsSpec.js | 118 +++++++++--------- 4 files changed, 99 insertions(+), 88 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 865311f..62db562 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. * Values titles: * [ - * onVar,onCondition,onLoop,omOperator,onLookAt,onEatLeft,onEatRight,onEatUp, + * onVar,onConst,onCondition,onLoop,omOperator,onLookAt,onEatLeft,onEatRight,onEatUp, * onEatDown,onStepLeft,onStepRight,onStepUp,onStepDown,onFromMem,onToMem, * onMyX,onMyY,onCheckLeft,onCheckRight,onCheckUp,onCheckDown * ] */ - orgOperatorWeights: [.1,.1,.001,.1,.01,2.,2.,2.,2.,2.,2.,2.,2.,.1,.1,.1,.1,.1,.1,.1,.1], + orgOperatorWeights: [.1,.1,.1,.001,.1,.01,2.,2.,2.,2.,2.,2.,2.,2.,.1,.1,.1,.1,.1,.1,.1,.1], /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of @@ -144,6 +144,10 @@ const Config = { * 0 and till Number.MAX_VALUE */ orgStartColor: 50, + /** + * {Number} Amount of bits for storing a numeric constant inside byte code + */ + codeConstBits: 16, /** * {Number} The value from -X/2 to X/2, which is used for setting * default value, while organism is delivering. So, if the value is diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index b58fc47..cb7efea 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -133,7 +133,7 @@ class Code2String { } _onConst(num) { - return `v${Num.getVar0(num)}=${Num.getBits(num, this.BITS_AFTER_THREE_VARS, Num.MAX_BITS)}`; + return `v${Num.getVar0(num)}=${Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeConstBits)}`; } _onCondition(num, line, lines) { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index c33aa12..d49f217 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -53,8 +53,6 @@ const OPERATORS = [ class OperatorsDos extends Operators { constructor(offs, vars, obs) { super(offs, vars, obs); - this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; - this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; /** * {Object} These operator handlers should return string, which * will be added to the final string script for evaluation. @@ -92,6 +90,9 @@ class OperatorsDos extends Operators { // working of mutations of operators. // Num.init(this._OPERATORS_CB.length); + + this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; + this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; } destroy() { @@ -117,8 +118,8 @@ class OperatorsDos extends Operators { } onConst(num, line, org) { - this.vars[Num.getVar0(num)] = Num.getBits(num, this.BITS_AFTER_ONE_VAR, Num.MAX_BITS); - org.energy -= OConfig.orgOperatorWeights[0]; + this.vars[Num.getVar0(num)] = Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.codeConstBits); + org.energy -= OConfig.orgOperatorWeights[1]; return ++line; } @@ -128,11 +129,11 @@ class OperatorsDos extends Operators { const cond = Num.getVar2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { - org.energy -= OConfig.orgOperatorWeights[1]; + org.energy -= OConfig.orgOperatorWeights[2]; return ++line; } - org.energy -= OConfig.orgOperatorWeights[1]; + org.energy -= OConfig.orgOperatorWeights[2]; return offs; } @@ -151,11 +152,11 @@ class OperatorsDos extends Operators { if (afterIteration === true) { if (++vars[var0] < vars[Num.getVar2(num)]) { this.offs.push(line, offs); - org.energy -= OConfig.orgOperatorWeights[2]; + org.energy -= OConfig.orgOperatorWeights[3]; return ++line; } - org.energy -= OConfig.orgOperatorWeights[2]; + org.energy -= OConfig.orgOperatorWeights[3]; return offs; } // @@ -165,18 +166,18 @@ class OperatorsDos extends Operators { vars[var0] = vars[Num.getVar1(num)]; if (vars[var0] < vars[Num.getVar2(num)]) { this.offs.push(line, offs); - org.energy -= OConfig.orgOperatorWeights[2]; + org.energy -= OConfig.orgOperatorWeights[3]; return ++line; } - org.energy -= OConfig.orgOperatorWeights[2]; + org.energy -= OConfig.orgOperatorWeights[3]; return offs; } onOperator(num, line, org) { const vars = this.vars; vars[Num.getVar0(num)] = OPERATORS[Num.getBits(num, this.BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[Num.getVar1(num)], vars[Num.getVar2(num)]); - org.energy -= OConfig.orgOperatorWeights[3]; + org.energy -= OConfig.orgOperatorWeights[4]; return ++line; } @@ -191,43 +192,43 @@ class OperatorsDos extends Operators { this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); vars[Num.getVar0(num)] = ret.ret; - org.energy -= OConfig.orgOperatorWeights[4]; + org.energy -= OConfig.orgOperatorWeights[5]; return ++line; } vars[Num.getVar0(num)] = 0; - org.energy -= OConfig.orgOperatorWeights[4]; + org.energy -= OConfig.orgOperatorWeights[5]; return ++line; } - onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[5]; return ++line} - onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} - onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} - onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} + onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} + onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} + onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} + onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[9]; return ++line} - onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[9]; return ++line} - onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} - onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} - onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} + onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} + onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} + onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} + onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[13]; return ++line} onFromMem(num, line, org) { this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; - org.energy -= OConfig.orgOperatorWeights[13]; + org.energy -= OConfig.orgOperatorWeights[14]; return ++line; } onToMem(num, line, org) { org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; - org.energy -= OConfig.orgOperatorWeights[14]; + org.energy -= OConfig.orgOperatorWeights[15]; return ++line; } - onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[15]; return ++line} - onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} + onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} + onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[17]; return ++line} - onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[17]; return energy} - onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[18]; return energy} - onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[19]; return energy} - onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[20]; return energy} + onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[18]; return energy} + onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[19]; return energy} + onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[20]; return energy} + onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[21]; return energy} _checkAt(num, line, org, x, y) { const ret = this._ret; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index d93628d..c33a6e9 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -21,30 +21,29 @@ describe("client/src/organism/OperatorsDos", () => { afterEach (() => {ops.destroy(); org.destroy()}); it("Checking variables working", () => { - expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 + expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x006fffff, 0, org)).toEqual(1); // 0x6 === 0b0110, var1 = var2 + expect(ops.onVar(0x006fffff, 0, org)).toEqual(1); // 0x6 === 0b0110, var1 = var2 expect(ops.vars).toEqual([0, 2, 2, 1]); - expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xf === 0b1111, var3 = var3 + expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xf === 0b1111, var3 = var3 expect(ops.vars).toEqual([0, 2, 2, 1]); }); it("Checking onVar() method with 3 bits per var config", () => { let bpv = OConfig.codeBitsPerVar; OConfig.codeBitsPerVar = 3; - let OperatorsDos = require('./Operators'); - let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7, 8], org); - - expect(ops1.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xff === 0b[111111]11, var8 = var8 - expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8]); - expect(ops1.onVar(0x005dffff, 0, org)).toEqual(1); // 0x5d === 0b[010111]01, var2 = var7 - expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); - expect(ops1.onVar(0x005fffff, 0, org)).toEqual(1); // 0x5f === 0b[010111]11, var2 = var7 - expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); - expect(ops1.onVar(0x0000ffff, 0, org)).toEqual(1); // 0x00 === 0b[000000]00, var0 = var0 - expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7, 8]); + let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); + + expect(ops1.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xff === 0b[111111]11, var7 = var7 + expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 7]); + expect(ops1.onVar(0x005dffff, 0, org)).toEqual(1); // 0x5d === 0b[010111]01, var2 = var7 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); + expect(ops1.onVar(0x005fffff, 0, org)).toEqual(1); // 0x5f === 0b[010111]11, var2 = var7 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); + expect(ops1.onVar(0x0000ffff, 0, org)).toEqual(1); // 0x00 === 0b[000000]00, var0 = var0 + expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); OConfig.codeBitsPerVar = bpv; ops1.destroy(); @@ -53,15 +52,15 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking onVar() energy decrease", () => { const energy = org.energy; const decrease = OConfig.orgOperatorWeights[0]; - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 expect(org.energy).toBe(energy - decrease); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 expect(org.energy).toBe(energy - decrease * 2); }); it('Checking line increase', () => { - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 - expect(ops.onVar(0x000fffff, 1, org)).toEqual(2); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 1, org)).toEqual(2); // 0x0 === 0b0000, var0 = var0 expect(ops.onVar(0x000fffff, 100, org)).toEqual(101); // 0x0 === 0b0000, var0 = var0 }); }); @@ -69,9 +68,52 @@ describe("client/src/organism/OperatorsDos", () => { describe('onConst() method', () => { let org; let ops; + let codeConstBits = OConfig.codeConstBits; + OConfig.codeConstBits = 16; beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); + afterAll (() => OConfig.codeConstBits = codeConstBits); + + it("Checking different constant values", () => { + expect(ops.onConst(0x01dfffff, 0, org)).toEqual(1); // 0xdffff === 0b[11][0111111111111111]11, var3 = 0x7fff + expect(ops.vars).toEqual([0, 1, 2, 0x7fff]); + expect(ops.onConst(0x010fffff, 0, org)).toEqual(1); // 0x0ffff === 0b[00][0011111111111111]11, var0 = 0x3fff + expect(ops.vars).toEqual([0x3fff, 1, 2, 0x7fff]); + expect(ops.onConst(0x01000000, 0, org)).toEqual(1); // 0x00000 === 0b[00][0000000000000000]00, var0 = 0x0000 + expect(ops.vars).toEqual([0, 1, 2, 0x7fff]); + }); + + it("Checking onConst() method with 3 bits per var config", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); + + expect(ops1.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 0xffff]); + expect(ops1.onConst(0x015dffff, 0, org)).toEqual(1); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff + expect(ops1.vars).toEqual([0, 1, 0xefff, 3, 4, 5, 6, 0xffff]); + expect(ops1.onConst(0x0100ffff, 0, org)).toEqual(1); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + expect(ops1.vars).toEqual([0x07ff, 1, 0xefff, 3, 4, 5, 6, 0xffff]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + + it("Checking onConst() energy decrease", () => { + const energy = org.energy; + const decrease = OConfig.orgOperatorWeights[1]; + expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(org.energy).toBe(energy - decrease); + expect(ops.onConst(0x0100ffff, 0, org)).toEqual(1); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + expect(org.energy).toBe(energy - decrease * 2); + }); + + it('Checking line increase', () => { + expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(ops.onConst(0x015dffff, 1, org)).toEqual(2); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff + expect(ops.onConst(0x0100ffff, 700, org)).toEqual(701); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + }); }); it("Checking onCondition() method", () => { @@ -88,7 +130,7 @@ describe("client/src/organism/OperatorsDos", () => { ops.destroy(); }); - it("Checking onLoop() method", () => { + it("Checking onLoop() method", () => { let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); expect(ops.onLoop(0x02ffffff, 0, {}, 2)).toEqual(2); //for(v3=v3;v3 { ops.destroy(); }); - // it("Checking onNot() method", () => { - // let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - // - // expect(ops.onNot(0x041fffff, 0, {}, 1)).toEqual(1); //'v0=!v1'; - // expect(ops.vars[0] === 0).toEqual(true); - // expect(ops.vars[1] === 1).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // expect(ops.onNot(0x046fffff, 1, {}, 1)).toEqual(2); //'v1=!v2'; - // expect(ops.vars[0] === 0).toEqual(true); - // expect(ops.vars[1] === 0).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 3).toEqual(true); - // expect(ops.onNot(0x04ffffff, 2, {}, 1)).toEqual(3); //'v3=!v3'; - // expect(ops.vars[0] === 0).toEqual(true); - // expect(ops.vars[1] === 0).toEqual(true); - // expect(ops.vars[2] === 2).toEqual(true); - // expect(ops.vars[3] === 0).toEqual(true); - // }); - // - // it("Checking onPi() method", () => { - // let ops = new OperatorsDos([]); - // - // expect(ops.onPi(0x053fffff), 0, 1).toEqual('v0=pi'); - // expect(ops.onPi(0x057fffff), 0, 1).toEqual('v1=pi'); - // expect(ops.onPi(0x05ffffff), 0, 1).toEqual('v3=pi'); - // }); - // - // it("Checking onTrig() method", () => { - // let ops = new OperatorsDos([]); - // - // expect(ops.onTrig(0x061bffff), 0, 1).toEqual('v0=Math.tan(v1)'); - // expect(ops.onTrig(0x0663ffff), 0, 1).toEqual('v1=Math.sin(v2)'); - // expect(ops.onTrig(0x06ffffff), 0, 1).toEqual('v3=Math.abs(v3)'); - // }); - it("Checking onLookAt() in a complex way", () => { let obs = new Observer(EVENT_AMOUNT); let ops = new OperatorsDos([], [1, 1, 2, 3], obs); From 285ad588263441f5f9bb2828a59fbb938610810d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 16 Feb 2018 16:32:34 +0200 Subject: [PATCH 176/291] fixed issue with constants in Code2String class small optimization of Operators.onCondition() operator fixed more tests #83 --- .../plugins/organisms/dos/Code2String.js | 13 +++--- .../plugins/organisms/dos/Operators.js | 18 ++++---- .../plugins/organisms/dos/OperatorsSpec.js | 44 +++++++++++++------ 3 files changed, 47 insertions(+), 28 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index cb7efea..16da49f 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -15,9 +15,6 @@ const CONDITION_BITS = 2; class Code2String { constructor(manager) { - this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; - this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; - this._manager = manager; /** * {Object} These operator handlers should return string representation @@ -65,6 +62,10 @@ class Code2String { this._offsets = []; Num.init(this._OPERATORS_CB_LEN); + + this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; + this.BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; + this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; // // API of the Manager for accessing outside. (e.g. from Console) // @@ -137,10 +138,10 @@ class Code2String { } _onCondition(num, line, lines) { - const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); - const cond = Num.getVar2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); + const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); + const blockOffs = Num.getBits(num, this.BITS_AFTER_THREE_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); - this._offsets.push(this._getOffs(line, lines, val3)); + this._offsets.push(this._getOffs(line, lines, blockOffs)); return `if(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index d49f217..cfca302 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -91,8 +91,9 @@ class OperatorsDos extends Operators { // Num.init(this._OPERATORS_CB.length); - this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; + this.BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; + this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; } destroy() { @@ -124,27 +125,26 @@ class OperatorsDos extends Operators { } onCondition(num, line, org, lines) { - const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); - const offs = this._getOffs(line, lines, val3); - const cond = Num.getVar2(num) >>> (OConfig.codeBitsPerVar - CONDITION_BITS); + const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { org.energy -= OConfig.orgOperatorWeights[2]; return ++line; } + const blockOffs = Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); org.energy -= OConfig.orgOperatorWeights[2]; - return offs; + return this._getOffs(line, lines, blockOffs); } /** * for(v0=v1; v0 { }); it('Checking line increase', () => { - expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff - expect(ops.onConst(0x015dffff, 1, org)).toEqual(2); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff - expect(ops.onConst(0x0100ffff, 700, org)).toEqual(701); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(ops.onConst(0x015dffff, 1, org)).toEqual(2); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff + expect(ops.onConst(0x0100ffff, 700, org)).toEqual(701); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff }); }); - it("Checking onCondition() method", () => { - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + describe('onCondition() method', () => { + let org; + let ops; - expect(ops.onCondition(0x01ffffff, 0, {}, 0)).toEqual(0); //if(v3!=v3)'); - expect(ops.onCondition(0x011fffff, 0, {}, 0)).toEqual(1); //if(v0!=v1)'); - expect(ops.onCondition(0x011abfff, 0, {}, 0)).toEqual(0); //if(v0==v1)'); - expect(ops.onCondition(0x01ffffff, 0, {}, 0)).toEqual(0); //if(v3!=v3)'); - expect(ops.onCondition(0x011fffff, 0, {}, 2)).toEqual(1); //if(v0!=v1)'); - expect(ops.onCondition(0x01ffffff, 0, {}, 2)).toEqual(2); //if(v3!=v3)'); - expect(ops.onCondition(0x01ffffff, 0, {}, 20)).toEqual(16); //if(v3!=v3)'); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); - ops.destroy(); + it("Checking conditions", () => { + expect(ops.onCondition(0x02ffffff, 0, org, 0)).toEqual(0); //if(v3!==v3)'); + expect(ops.onCondition(0x021fffff, 0, org, 0)).toEqual(1); //if(v0!==v1)'); + expect(ops.onCondition(0x021abfff, 0, org, 0)).toEqual(0); //if(v0===v1)'); + expect(ops.onCondition(0x0213ffff, 0, org, 0)).toEqual(1); //if(v0 < v1)'); + }); + + it('Checking closing bracket offset', () => { + expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0, org, 1)).toEqual(1); //if(v3!==v3)'); + expect(ops.onCondition(0x0213ffff, 0, org, 2)).toEqual(1); //if(v0 < v1)'); + }); + + // it() with 3 bits per var + it('Checking energy decrease', () => { + const energy = org.energy; + const decrease = OConfig.orgOperatorWeights[2]; + + expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); + expect(org.energy).toBe(energy - decrease); + expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); + expect(org.energy).toBe(energy - decrease * 2); + }); }); it("Checking onLoop() method", () => { From 6da316d66c5d366554bb674d11983bdb0ec7c5c8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 16 Feb 2018 20:31:23 +0200 Subject: [PATCH 177/291] onCondition() operator optimization fixed more tests #83 --- .../plugins/organisms/dos/Operators.js | 18 +++------ .../plugins/organisms/dos/OperatorsSpec.js | 38 +++++++++++++------ client/src/vm/VM.js | 14 +++---- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index cfca302..8288cde 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -124,7 +124,7 @@ class OperatorsDos extends Operators { return ++line; } - onCondition(num, line, org, lines) { + onCondition(num, line, org) { const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { @@ -134,7 +134,7 @@ class OperatorsDos extends Operators { const blockOffs = Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); org.energy -= OConfig.orgOperatorWeights[2]; - return this._getOffs(line, lines, blockOffs); + return this._getOffs(line, blockOffs); } /** @@ -144,7 +144,7 @@ class OperatorsDos extends Operators { const vars = this.vars; const var0 = Num.getVar0(num); const blockOffs = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); - const offs = this._getOffs(line, lines, blockOffs); + const offs = this._getOffs(line, blockOffs); // // If last iteration has done and we've returned to the line, // where "for" operator is located @@ -279,20 +279,12 @@ class OperatorsDos extends Operators { * So it's possible to set it to one of 1...3. So we change it in * real time to fix the overlap problem. * @param {Number} line Current line index - * @param {Number} lines Amount of lines * @param {Number} offs Local offset of closing bracket we want to set * @returns {Number} */ - _getOffs(line, lines, offs) { - const offset = line + offs < lines ? line + offs + 1 : lines; + _getOffs(line, offs) { const offsets = this.offs; - const length = offsets.length; - - if (length > 0 && offset >= offsets[length - 1]) { - return offsets[length - 1]; - } - - return offset; + return line + offs > offsets[offsets.length - 1] ? offsets[offsets.length - 1] : line + offs; } } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 0d3924c..be7174e 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -120,30 +120,46 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking conditions", () => { - expect(ops.onCondition(0x02ffffff, 0, org, 0)).toEqual(0); //if(v3!==v3)'); - expect(ops.onCondition(0x021fffff, 0, org, 0)).toEqual(1); //if(v0!==v1)'); - expect(ops.onCondition(0x021abfff, 0, org, 0)).toEqual(0); //if(v0===v1)'); - expect(ops.onCondition(0x0213ffff, 0, org, 0)).toEqual(1); //if(v0 < v1)'); + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); + expect(ops.onCondition(0x021fffff, 0, org)).toEqual(1); //if(v0!==v1)'); + expect(ops.onCondition(0x021abfff, 0, org)).toEqual(1); //if(v0===v1)'); + expect(ops.onCondition(0x0213ffff, 0, org)).toEqual(1); //if(v0 < v1)'); }); it('Checking closing bracket offset', () => { - expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); - expect(ops.onCondition(0x02ffffff, 0, org, 1)).toEqual(1); //if(v3!==v3)'); - expect(ops.onCondition(0x0213ffff, 0, org, 2)).toEqual(1); //if(v0 < v1)'); + ops.offsets = [2]; + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(2); //if(v3!==v3)'); + ops.offsets = [1]; + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); + ops.offsets = [1]; + expect(ops.onCondition(0x0213ffff, 0, org)).toEqual(1); //if(v0 < v1)'); + }); + + it("Checking onCondition() method with 3 bits per var config", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); + + ops.offsets = [2]; + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(2); //if(v3!==v3)'); + ops.offsets = [2]; + expect(ops.onCondition(0x021fffff, 0, org)).toEqual(1); //if(v0!==v7)'); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); }); - // it() with 3 bits per var it('Checking energy decrease', () => { const energy = org.energy; const decrease = OConfig.orgOperatorWeights[2]; - expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); expect(org.energy).toBe(energy - decrease); - expect(ops.onCondition(0x02ffffff, 0, org, 2)).toEqual(2); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); expect(org.energy).toBe(energy - decrease * 2); }); }); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 2f9d136..19543ea 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -36,12 +36,6 @@ class VM extends Observer { * script parts for current VM instance */ this._operatorCls = operatorCls; - /** - * {Array} Array of two numbers. first - line number where we have - * to return if first line appears. second - line number, where ends - * closing block '}' of block operator (e.g. for, if,...). - */ - this._offsets = []; this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); /** * {Function} Class, which implement all supported operators @@ -49,6 +43,12 @@ class VM extends Observer { this._operators = new operatorCls(this._offsets, this._vars, obs); this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; + /** + * {Array} Array of two numbers. first - line number where we have + * to return if first line appears. second - line number, where ends + * closing block '}' of block operator (e.g. for, if,...). + */ + this._offsets = [this._code.length]; this._line = 0; } @@ -253,7 +253,7 @@ class VM extends Observer { _reset() { this.fire(EVENTS.RESET_CODE); this._line = 0; - this._operators.offsets = (this._offsets = []); + this._operators.offsets = (this._offsets = [this._code.length]); } /** From 40cb5a052e176d8682477b9af5d39373e86761b8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 00:04:08 +0200 Subject: [PATCH 178/291] for loop changed to while found critical issue with if block optimized VM fixed more tests #83 --- .../plugins/organisms/dos/Code2String.js | 11 +++--- .../plugins/organisms/dos/Operators.js | 39 +++++-------------- .../plugins/organisms/dos/OperatorsSpec.js | 4 ++ client/src/vm/VM.js | 33 +++++++--------- 4 files changed, 35 insertions(+), 52 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 16da49f..8addcd1 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -139,17 +139,18 @@ class Code2String { _onCondition(num, line, lines) { const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); - const blockOffs = Num.getBits(num, this.BITS_AFTER_THREE_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); + const blockOffs = Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); this._offsets.push(this._getOffs(line, lines, blockOffs)); return `if(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } _onLoop(num, line, lines) { - const var0 = Num.getVar0(num); - const val3 = Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeBitsPerBlock); - this._offsets.push(this._getOffs(line, lines, val3)); - return `for(v${var0}=v${Num.getVar1(num)};v${var0} offsets[offsets.length - 1] ? offsets[offsets.length - 1] : line + offs; + const offsets = this.offs || []; + return line + offs > offsets[offsets.length - 1] ? offsets[offsets.length - 1] : line + offs + 1; } } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index be7174e..8c55776 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -125,8 +125,11 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking conditions", () => { expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); + ops.offsets = [1]; expect(ops.onCondition(0x021fffff, 0, org)).toEqual(1); //if(v0!==v1)'); + ops.offsets = [1]; expect(ops.onCondition(0x021abfff, 0, org)).toEqual(1); //if(v0===v1)'); + ops.offsets = [1]; expect(ops.onCondition(0x0213ffff, 0, org)).toEqual(1); //if(v0 < v1)'); }); @@ -159,6 +162,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); expect(org.energy).toBe(energy - decrease); + ops.offsets = [1]; expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); expect(org.energy).toBe(energy - decrease * 2); }); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 19543ea..da08a87 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -37,11 +37,6 @@ class VM extends Observer { */ this._operatorCls = operatorCls; this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); - /** - * {Function} Class, which implement all supported operators - */ - this._operators = new operatorCls(this._offsets, this._vars, obs); - this._ops = this._operators.operators; this._code = parent && parent.code.slice() || []; /** * {Array} Array of two numbers. first - line number where we have @@ -49,6 +44,11 @@ class VM extends Observer { * closing block '}' of block operator (e.g. for, if,...). */ this._offsets = [this._code.length]; + /** + * {Function} Class, which implement all supported operators + */ + this._operators = new operatorCls(this._offsets, this._vars, obs); + this._ops = this._operators.operators; this._line = 0; } @@ -94,27 +94,24 @@ class VM extends Observer { const OFFS = Num.VAR_BITS_OFFS; let len = period; let line = this._line; - let ret = false; while (len > 0 && org.energy > 0) { - line = ops[code[line] >>> OFFS](code[line], line, org, lines, ret); - // - // We reach the end of the script and have to run it from the beginning - // - if (line >= lines && org.energy > 0) { - line = 0; - this._operators.offsets = this._offsets = []; - len--; - continue; - } + line = ops[code[line] >>> OFFS](code[line], line, org, lines); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) // - if ((ret = (offs.length > 0 && line === offs[offs.length - 1]))) { + if (line === offs[offs.length - 1]) { offs.pop(); line = offs.pop(); } + // + // We reach the end of the script and have to run it from the beginning + // + if (line >= lines && org.energy > 0) { + line = 0; + this._operators.offsets = this._offsets = [code.length]; + } len--; } this._line = line; @@ -126,7 +123,7 @@ class VM extends Observer { this._operators.destroy && this._operators.destroy(); this._operators = null; this._operatorCls = null; - this._offsets = null; + this._offsets = []; this._vars = null; this._code = null; this._obs = null; From c7d53ddc1be29f199aa1433d128c3039139eea7b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 00:49:08 +0200 Subject: [PATCH 179/291] fixed incorrect behavior of onLoop operator #83 --- client/src/manager/plugins/organisms/dos/Operators.js | 2 +- client/src/vm/VM.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 9ecc9ac..2583ed9 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -264,7 +264,7 @@ class OperatorsDos extends Operators { * @returns {Number} */ _getOffs(line, offs) { - const offsets = this.offs || []; + const offsets = this.offs || [0]; return line + offs > offsets[offsets.length - 1] ? offsets[offsets.length - 1] : line + offs + 1; } } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index da08a87..7742f87 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -101,7 +101,7 @@ class VM extends Observer { // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) // - if (line === offs[offs.length - 1]) { + if (offs.length > 1 && line === offs[offs.length - 1]) { offs.pop(); line = offs.pop(); } From 7cdccde0587556c74577f766e875bca30277032e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 13:26:53 +0200 Subject: [PATCH 180/291] Operators class refactoring fixed few more tests #83 --- .../src/manager/plugins/organisms/Organism.js | 4 +- .../plugins/organisms/dos/Code2String.js | 22 +- .../plugins/organisms/dos/Operators.js | 72 +++--- .../plugins/organisms/dos/OperatorsSpec.js | 240 +++++++----------- .../plugins/organisms/garmin/Operators.js | 2 +- client/src/vm/VM.js | 9 +- 6 files changed, 139 insertions(+), 210 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index c612d14..41d2843 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -220,7 +220,7 @@ class Organism extends Observer { } _create() { - this.vm = new VM(this, this._operatorCls); + this.vm = new VM(this, this._operatorCls, OConfig.orgOperatorWeights); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; this._colorIndex = OConfig.orgStartColor * Num.MAX_BITS; @@ -234,7 +234,7 @@ class Organism extends Observer { } _clone(parent) { - this.vm = new VM(this, this._operatorCls, parent.vm); + this.vm = new VM(this, this._operatorCls, OConfig.orgOperatorWeights, parent.vm); this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 8addcd1..4b2ec16 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -63,9 +63,9 @@ class Code2String { Num.init(this._OPERATORS_CB_LEN); - this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; - this.BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; - this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; + this._BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; + this._BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; + this._BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; // // API of the Manager for accessing outside. (e.g. from Console) // @@ -134,27 +134,27 @@ class Code2String { } _onConst(num) { - return `v${Num.getVar0(num)}=${Num.getBits(num, this.BITS_AFTER_THREE_VARS, OConfig.codeConstBits)}`; + return `v${Num.getVar0(num)}=${Num.getBits(num, this._BITS_AFTER_THREE_VARS, OConfig.codeConstBits)}`; } _onCondition(num, line, lines) { - const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); - const blockOffs = Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); + const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); + const blockOffs = Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); this._offsets.push(this._getOffs(line, lines, blockOffs)); return `if(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } _onLoop(num, line, lines) { - const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); - const blockOffs = Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); + const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); + const blockOffs = Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); this._offsets.push(this._getOffs(line, lines, blockOffs)); return `while(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } _onOperator(num) { - return `v${Num.getVar0(num)}=v${Num.getVar1(num)}${this._OPERATORS[Num.getBits(num, this.BITS_AFTER_THREE_VARS, FOUR_BITS)]}v${Num.getVar2(num)}`; + return `v${Num.getVar0(num)}=v${Num.getVar1(num)}${this._OPERATORS[Num.getBits(num, this._BITS_AFTER_THREE_VARS, FOUR_BITS)]}v${Num.getVar2(num)}`; } _onLookAt(num) { @@ -194,11 +194,11 @@ class Code2String { } _onFromMem(num) { - return `v${Num.getVar0(num)}=fromMem(${Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; + return `v${Num.getVar0(num)}=fromMem(${Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; } _onToMem(num) { - return `toMem(v${Num.getVar0(num)},${Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; + return `toMem(v${Num.getVar0(num)},${Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; } _onMyX(num) { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 2583ed9..290b318 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -91,9 +91,9 @@ class OperatorsDos extends Operators { // Num.init(this._OPERATORS_CB.length); - this.BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; - this.BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; - this.BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; + this._BITS_AFTER_ONE_VAR = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR; + this._BITS_AFTER_TWO_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 2; + this._BITS_AFTER_THREE_VARS = Num.BITS_PER_OPERATOR + Num.BITS_PER_VAR * 3; } destroy() { @@ -109,56 +109,48 @@ class OperatorsDos extends Operators { * * @param {Number} num Packed into number vm line * @param {Number} line Current line in vm - * @param {Organism} org Current organism * @return {Number} Parsed vm line string */ - onVar(num, line, org) { + onVar(num, line) { this.vars[Num.getVar0(num)] = this.vars[Num.getVar1(num)]; - org.energy -= OConfig.orgOperatorWeights[0]; return ++line; } - onConst(num, line, org) { - this.vars[Num.getVar0(num)] = Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.codeConstBits); - org.energy -= OConfig.orgOperatorWeights[1]; + onConst(num, line) { + this.vars[Num.getVar0(num)] = Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.codeConstBits); return ++line; } - onCondition(num, line, org) { - const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); - const offs = this._getOffs(line, Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock)); + onCondition(num, line) { + const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); + const offs = this._getOffs(line, Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock)); if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { this.offs.push(offs, offs); - org.energy -= OConfig.orgOperatorWeights[2]; return ++line; } - org.energy -= OConfig.orgOperatorWeights[2]; return offs; } /** * while(v0 op v2) goto offs */ - onLoop(num, line, org) { - const cond = Num.getBits(num, this.BITS_AFTER_TWO_VARS, CONDITION_BITS); - const offs = this._getOffs(line, Num.getBits(num, this.BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock)); + onLoop(num, line) { + const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); + const offs = this._getOffs(line, Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock)); if (CONDITIONS[cond](this.vars[Num.getVar0(num)], this.vars[Num.getVar1(num)])) { this.offs.push(line, offs); - org.energy -= OConfig.orgOperatorWeights[3]; return ++line; } - org.energy -= OConfig.orgOperatorWeights[3]; return offs; } - onOperator(num, line, org) { + onOperator(num, line) { const vars = this.vars; - vars[Num.getVar0(num)] = OPERATORS[Num.getBits(num, this.BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[Num.getVar1(num)], vars[Num.getVar2(num)]); - org.energy -= OConfig.orgOperatorWeights[4]; + vars[Num.getVar0(num)] = OPERATORS[Num.getBits(num, this._BITS_AFTER_THREE_VARS, FOUR_BITS)](vars[Num.getVar1(num)], vars[Num.getVar2(num)]); return ++line; } @@ -173,43 +165,39 @@ class OperatorsDos extends Operators { this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); vars[Num.getVar0(num)] = ret.ret; - org.energy -= OConfig.orgOperatorWeights[5]; return ++line; } vars[Num.getVar0(num)] = 0; - org.energy -= OConfig.orgOperatorWeights[5]; return ++line; } - onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[6]; return ++line} - onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[7]; return ++line} - onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[8]; return ++line} - onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[9]; return ++line} + onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); return ++line} + onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); return ++line} + onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} + onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} - onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[10]; return ++line} - onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; org.energy -= OConfig.orgOperatorWeights[11]; return ++line} - onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; org.energy -= OConfig.orgOperatorWeights[12]; return ++line} - onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; org.energy -= OConfig.orgOperatorWeights[13]; return ++line} + onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; return ++line} + onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; return ++line} + onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; return ++line} + onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} onFromMem(num, line, org) { - this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; - org.energy -= OConfig.orgOperatorWeights[14]; + this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; return ++line; } onToMem(num, line, org) { - org.mem[Num.getBits(num, this.BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; - org.energy -= OConfig.orgOperatorWeights[15]; + org.mem[Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; return ++line; } - onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; org.energy -= OConfig.orgOperatorWeights[16]; return ++line} - onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; org.energy -= OConfig.orgOperatorWeights[17]; return ++line} + onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; return ++line} + onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; return ++line} - onCheckLeft(num, line, org) {const energy = this._checkAt(num, line, org, org.x - 1, org.y); org.energy -= OConfig.orgOperatorWeights[18]; return energy} - onCheckRight(num, line, org) {const energy = this._checkAt(num, line, org, org.x + 1, org.y); org.energy -= OConfig.orgOperatorWeights[19]; return energy} - onCheckUp(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y - 1); org.energy -= OConfig.orgOperatorWeights[20]; return energy} - onCheckDown(num, line, org) {const energy = this._checkAt(num, line, org, org.x, org.y + 1); org.energy -= OConfig.orgOperatorWeights[21]; return energy} + onCheckLeft(num, line, org) {return this._checkAt(num, line, org, org.x - 1, org.y)} + onCheckRight(num, line, org) {return this._checkAt(num, line, org, org.x + 1, org.y)} + onCheckUp(num, line, org) {return this._checkAt(num, line, org, org.x, org.y - 1)} + onCheckDown(num, line, org) {return this._checkAt(num, line, org, org.x, org.y + 1)} _checkAt(num, line, org, x, y) { const ret = this._ret; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 8c55776..b3a3f33 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -21,13 +21,13 @@ describe("client/src/organism/OperatorsDos", () => { afterEach (() => {ops.destroy(); org.destroy()}); it("Checking variables working", () => { - expect(ops.onVar(0x00dfffff, 0, org)).toEqual(1); // 0xd === 0b1101, var3 = var1 + expect(ops.onVar(0x00dfffff, 0)).toEqual(1); // 0xd === 0b1101, var3 = var1 expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0)).toEqual(1); // 0x0 === 0b0000, var0 = var0 expect(ops.vars).toEqual([0, 1, 2, 1]); - expect(ops.onVar(0x006fffff, 0, org)).toEqual(1); // 0x6 === 0b0110, var1 = var2 + expect(ops.onVar(0x006fffff, 0)).toEqual(1); // 0x6 === 0b0110, var1 = var2 expect(ops.vars).toEqual([0, 2, 2, 1]); - expect(ops.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xf === 0b1111, var3 = var3 + expect(ops.onVar(0x00ffffff, 0)).toEqual(1); // 0xf === 0b1111, var3 = var3 expect(ops.vars).toEqual([0, 2, 2, 1]); }); @@ -36,32 +36,23 @@ describe("client/src/organism/OperatorsDos", () => { OConfig.codeBitsPerVar = 3; let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); - expect(ops1.onVar(0x00ffffff, 0, org)).toEqual(1); // 0xff === 0b[111111]11, var7 = var7 + expect(ops1.onVar(0x00ffffff, 0)).toEqual(1); // 0xff === 0b[111111]11, var7 = var7 expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 7]); - expect(ops1.onVar(0x005dffff, 0, org)).toEqual(1); // 0x5d === 0b[010111]01, var2 = var7 + expect(ops1.onVar(0x005dffff, 0)).toEqual(1); // 0x5d === 0b[010111]01, var2 = var7 expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); - expect(ops1.onVar(0x005fffff, 0, org)).toEqual(1); // 0x5f === 0b[010111]11, var2 = var7 + expect(ops1.onVar(0x005fffff, 0)).toEqual(1); // 0x5f === 0b[010111]11, var2 = var7 expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); - expect(ops1.onVar(0x0000ffff, 0, org)).toEqual(1); // 0x00 === 0b[000000]00, var0 = var0 + expect(ops1.onVar(0x0000ffff, 0)).toEqual(1); // 0x00 === 0b[000000]00, var0 = var0 expect(ops1.vars).toEqual([0, 1, 7, 3, 4, 5, 6, 7]); OConfig.codeBitsPerVar = bpv; ops1.destroy(); }); - it("Checking onVar() energy decrease", () => { - const energy = org.energy; - const decrease = OConfig.orgOperatorWeights[0]; - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 - expect(org.energy).toBe(energy - decrease); - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 - expect(org.energy).toBe(energy - decrease * 2); - }); - it('Checking line increase', () => { - expect(ops.onVar(0x000fffff, 0, org)).toEqual(1); // 0x0 === 0b0000, var0 = var0 - expect(ops.onVar(0x000fffff, 1, org)).toEqual(2); // 0x0 === 0b0000, var0 = var0 - expect(ops.onVar(0x000fffff, 100, org)).toEqual(101); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 0)).toEqual(1); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 1)).toEqual(2); // 0x0 === 0b0000, var0 = var0 + expect(ops.onVar(0x000fffff, 100)).toEqual(101); // 0x0 === 0b0000, var0 = var0 }); }); @@ -76,11 +67,11 @@ describe("client/src/organism/OperatorsDos", () => { afterAll (() => OConfig.codeConstBits = codeConstBits); it("Checking different constant values", () => { - expect(ops.onConst(0x01dfffff, 0, org)).toEqual(1); // 0xdffff === 0b[11][0111111111111111]11, var3 = 0x7fff + expect(ops.onConst(0x01dfffff, 0)).toEqual(1); // 0xdffff === 0b[11][0111111111111111]11, var3 = 0x7fff expect(ops.vars).toEqual([0, 1, 2, 0x7fff]); - expect(ops.onConst(0x010fffff, 0, org)).toEqual(1); // 0x0ffff === 0b[00][0011111111111111]11, var0 = 0x3fff + expect(ops.onConst(0x010fffff, 0)).toEqual(1); // 0x0ffff === 0b[00][0011111111111111]11, var0 = 0x3fff expect(ops.vars).toEqual([0x3fff, 1, 2, 0x7fff]); - expect(ops.onConst(0x01000000, 0, org)).toEqual(1); // 0x00000 === 0b[00][0000000000000000]00, var0 = 0x0000 + expect(ops.onConst(0x01000000, 0)).toEqual(1); // 0x00000 === 0b[00][0000000000000000]00, var0 = 0x0000 expect(ops.vars).toEqual([0, 1, 2, 0x7fff]); }); @@ -89,30 +80,21 @@ describe("client/src/organism/OperatorsDos", () => { OConfig.codeBitsPerVar = 3; let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); - expect(ops1.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(ops1.onConst(0x01ffffff, 0)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff expect(ops1.vars).toEqual([0, 1, 2, 3, 4, 5, 6, 0xffff]); - expect(ops1.onConst(0x015dffff, 0, org)).toEqual(1); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff + expect(ops1.onConst(0x015dffff, 0)).toEqual(1); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff expect(ops1.vars).toEqual([0, 1, 0xefff, 3, 4, 5, 6, 0xffff]); - expect(ops1.onConst(0x0100ffff, 0, org)).toEqual(1); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + expect(ops1.onConst(0x0100ffff, 0)).toEqual(1); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff expect(ops1.vars).toEqual([0x07ff, 1, 0xefff, 3, 4, 5, 6, 0xffff]); OConfig.codeBitsPerVar = bpv; ops1.destroy(); }); - it("Checking onConst() energy decrease", () => { - const energy = org.energy; - const decrease = OConfig.orgOperatorWeights[1]; - expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff - expect(org.energy).toBe(energy - decrease); - expect(ops.onConst(0x0100ffff, 0, org)).toEqual(1); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff - expect(org.energy).toBe(energy - decrease * 2); - }); - it('Checking line increase', () => { - expect(ops.onConst(0x01ffffff, 0, org)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff - expect(ops.onConst(0x015dffff, 1, org)).toEqual(2); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff - expect(ops.onConst(0x0100ffff, 700, org)).toEqual(701); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff + expect(ops.onConst(0x01ffffff, 0)).toEqual(1); // 0xfffff === 0b[111][1111111111111111]1, var7 = 0xffff + expect(ops.onConst(0x015dffff, 1)).toEqual(2); // 0x5dfff === 0b[010][1110111111111111]1, var2 = 0xefff + expect(ops.onConst(0x0100ffff, 700)).toEqual(701); // 0x00fff === 0b[000][0000011111111111]1, var0 = 0x07ff }); }); @@ -124,22 +106,22 @@ describe("client/src/organism/OperatorsDos", () => { afterEach (() => {ops.destroy(); org.destroy()}); it("Checking conditions", () => { - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0)).toEqual(1); //if(v3!==v3); ops.offsets = [1]; - expect(ops.onCondition(0x021fffff, 0, org)).toEqual(1); //if(v0!==v1)'); + expect(ops.onCondition(0x021fffff, 0)).toEqual(1); //if(v0!==v1); ops.offsets = [1]; - expect(ops.onCondition(0x021abfff, 0, org)).toEqual(1); //if(v0===v1)'); + expect(ops.onCondition(0x021abfff, 0)).toEqual(1); //if(v0===v1); ops.offsets = [1]; - expect(ops.onCondition(0x0213ffff, 0, org)).toEqual(1); //if(v0 < v1)'); + expect(ops.onCondition(0x0213ffff, 0)).toEqual(1); //if(v0 < v1); }); it('Checking closing bracket offset', () => { ops.offsets = [2]; - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(2); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0)).toEqual(2); //if(v3!==v3); ops.offsets = [1]; - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0)).toEqual(1); //if(v3!==v3); ops.offsets = [1]; - expect(ops.onCondition(0x0213ffff, 0, org)).toEqual(1); //if(v0 < v1)'); + expect(ops.onCondition(0x0213ffff, 0)).toEqual(1); //if(v0 < v1); }); it("Checking onCondition() method with 3 bits per var config", () => { @@ -148,133 +130,87 @@ describe("client/src/organism/OperatorsDos", () => { let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); ops.offsets = [2]; - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(2); //if(v3!==v3)'); + expect(ops.onCondition(0x02ffffff, 0)).toEqual(2); //if(v3!==v3); ops.offsets = [2]; - expect(ops.onCondition(0x021fffff, 0, org)).toEqual(1); //if(v0!==v7)'); + expect(ops.onCondition(0x021fffff, 0)).toEqual(1); //if(v0!==v7); OConfig.codeBitsPerVar = bpv; ops1.destroy(); }); - - it('Checking energy decrease', () => { - const energy = org.energy; - const decrease = OConfig.orgOperatorWeights[2]; - - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); - expect(org.energy).toBe(energy - decrease); - ops.offsets = [1]; - expect(ops.onCondition(0x02ffffff, 0, org)).toEqual(1); //if(v3!==v3)'); - expect(org.energy).toBe(energy - decrease * 2); - }); }); - it("Checking onLoop() method", () => { - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - - expect(ops.onLoop(0x02ffffff, 0, {}, 2)).toEqual(2); //for(v3=v3;v3 { - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); - - expect(ops.onLoop(0x028fffff, 0, {}, 20)).toEqual(1); //for(v2=v0;v2 { + let org; + let ops; - ops.destroy(); - }); - it("Checking onLoop() method 3", () => { - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); - expect(ops.onLoop(0x0287ffff, 0, {}, 15)).toEqual(1); //for(v2=v0;v2 { + expect(ops.onCondition(0x03ffffff, 0)).toEqual(1); //while(v3!==v3); + ops.offsets = [1]; + expect(ops.onCondition(0x031fffff, 0)).toEqual(1); //while(v0!==v1); + ops.offsets = [1]; + expect(ops.onCondition(0x031abfff, 0)).toEqual(1); //while(v0===v1); + ops.offsets = [1]; + expect(ops.onCondition(0x0313ffff, 0)).toEqual(1); //while(v0 < v1); + }); - ops.destroy(); - }); + it('Checking closing bracket offset', () => { + ops.offsets = [2]; + expect(ops.onCondition(0x03ffffff, 0)).toEqual(2); //while(v3!==v3); + ops.offsets = [1]; + expect(ops.onCondition(0x03ffffff, 0)).toEqual(1); //while(v3!==v3); + ops.offsets = [1]; + expect(ops.onCondition(0x0313ffff, 0)).toEqual(1); //while(v0 < v1); + }); - it("Checking onOperator() method", () => { - let ops = new OperatorsDos([], [0, 3, 1, 3], new Observer()); + it("Checking onLoop() method with 3 bits per var config", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([], [0, 1, 2, 3, 4, 5, 6, 7], org); - expect(ops.onOperator(0x031a3fff, 0, {}, 1)).toEqual(1); //'v0=v1>>v2'; - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 3).toEqual(true); - expect(ops.vars[2] === 1).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); + ops.offsets = [2]; + expect(ops.onCondition(0x03ffffff, 0)).toEqual(2); //while(v3!==v3); + ops.offsets = [2]; + expect(ops.onCondition(0x031fffff, 0)).toEqual(1); //while(v0!==v7); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); - it("Checking onOperator() method 2", () => { - let ops = new OperatorsDos([], [0, 3, 1, 3], new Observer()); - expect(ops.onOperator(0x036c7fff, 1, {}, 1)).toEqual(2); //'v1=v2-v3'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === -2).toEqual(true); - expect(ops.vars[2] === 1).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); + describe('onOperator() method', () => { + let org; + let ops; - ops.destroy(); - }); - it("Checking onOperator() method 3", () => { - let ops = new OperatorsDos([], [0, 3, 1, 3], new Observer()); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); - expect(ops.onOperator(0x036fffff, 3, 1)).toEqual(4); //'v1=v2<=v3'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 1).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); + it("Checking onOperator() method", () => { + expect(ops.onOperator(0x045a3fff, 0)).toEqual(1); //v1=v1>>v2; + expect(ops.vars).toEqual([0, 0, 2, 3]); + expect(ops.onOperator(0x046c7fff, 1)).toEqual(2); //v1=v2-v3; + expect(ops.vars).toEqual([0, -1, 2, 3]); + expect(ops.onOperator(0x046fffff, 3)).toEqual(4); //v1=v2<=v3; + expect(ops.vars).toEqual([0, 1, 2, 3]); + expect(ops.onOperator(0x04ffffff, 7)).toEqual(8); //v3=v3<=v3; + expect(ops.vars).toEqual([0, 1, 2, 1]); + }); - ops.destroy(); - }); - it("Checking onOperator() method 3", () => { - let ops = new OperatorsDos([], [0, 3, 1, 3], new Observer()); + it('Checking onOperator() with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); - expect(ops.onOperator(0x03ffffff, 7, {}, 1)).toEqual(8); //'v3=v3<=v3'; - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 3).toEqual(true); - expect(ops.vars[2] === 1).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); + expect(ops1.onOperator(0x04ffffff, 0)).toEqual(1); //v15=v15<=v15 + expect(ops1.vars).toEqual([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1]); + expect(ops1.onOperator(0x046ff0ff, 0)).toEqual(1); //v6=v15+v15 + expect(ops1.vars).toEqual([0,1,2,3,4,5,2,7,8,9,10,11,12,13,14,1]); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); it("Checking onLookAt() in a complex way", () => { diff --git a/client/src/manager/plugins/organisms/garmin/Operators.js b/client/src/manager/plugins/organisms/garmin/Operators.js index 7411e4a..45b70f4 100644 --- a/client/src/manager/plugins/organisms/garmin/Operators.js +++ b/client/src/manager/plugins/organisms/garmin/Operators.js @@ -102,7 +102,7 @@ class OperatorsGarmin extends Operators { // onLoop(num, line, org, lines, ret) { // const vars = this.vars; // const var0 = VAR0(num); -// const val3 = Num.getBits(num, BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); +// const val3 = Num.getBits(num, _BITS_AFTER_THREE_VARS, Num.BITS_OF_TWO_VARS); // const offs = line + val3 < lines ? line + val3 + 1 : lines; // // if (ret) { diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 7742f87..56d1b87 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -25,12 +25,14 @@ class VM extends Observer { * cloning mode and we have to create a copy of it. * @param {Observer} obs observer for external events firing * @param {Function} operatorCls Class of operators + * @param {Array} weights Weights of operations * @param {VM} parent Parent VM instance in case of cloning */ - constructor(obs, operatorCls, parent = null) { + constructor(obs, operatorCls, weights, parent = null) { super(EVENT_AMOUNT); this._obs = obs; + this._weights = weights; /** * {Function} Class of operators, with implementation of all available * script parts for current VM instance @@ -94,9 +96,12 @@ class VM extends Observer { const OFFS = Num.VAR_BITS_OFFS; let len = period; let line = this._line; + let operator; while (len > 0 && org.energy > 0) { - line = ops[code[line] >>> OFFS](code[line], line, org, lines); + operator = code[line] >>> OFFS; + line = ops[operator](code[line], line, org, lines); + org.energy -= this._weights[operator]; // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From b9f912f37f0dd1c0c03b368465726b5d94fb478f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 15:25:47 +0200 Subject: [PATCH 181/291] fixed more tests #83 fixed NaN value in DOS script --- .../plugins/organisms/dos/Operators.js | 12 ++++--- .../plugins/organisms/dos/OperatorsSpec.js | 35 +++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 290b318..90b2d6b 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -18,11 +18,13 @@ const Num = require('./../../../../vm/Num'); */ const IN_WORLD = Helper.inWorld; const IS_FINITE = Number.isFinite; +const IS_NAN = Number.isNaN; /** * {Function} Just a shortcuts */ const FOUR_BITS = 4; const CONDITION_BITS = 2; +const MAX_VAL = Number.MAX_VALUE; /** * {Array} Available conditions for if operator. Amount should be * the same like (1 << Num.BITS_PER_VAR) @@ -32,11 +34,11 @@ const CONDITIONS = [(a,b)=>aa>b, (a,b)=>a===b, (a,b)=>a!==b]; * {Array} Available operators for math calculations */ const OPERATORS = [ - (a,b) => {const v=a+b; return IS_FINITE(v)?v:0}, - (a,b) => {const v=a-b; return IS_FINITE(v)?v:0}, - (a,b) => {const v=a*b; return IS_FINITE(v)?v:0}, - (a,b) => {const v=a/b; return IS_FINITE(v)?v:0}, - (a,b) => {const v=a%b; return IS_FINITE(v)?v:0}, + (a,b) => {const v=a+b; return IS_FINITE(v)?v:MAX_VAL}, + (a,b) => {const v=a-b; return IS_FINITE(v)?v:-MAX_VAL}, + (a,b) => {const v=a*b; return IS_FINITE(v)?v:MAX_VAL}, + (a,b) => {const v=a/b; return IS_FINITE(v)?v:MAX_VAL}, + (a,b) => {const v=a%b; return IS_NAN(v)?0:v}, (a,b) => a&b, (a,b) => a|b, (a,b) => a^b, diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index b3a3f33..f04dff9 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -196,6 +196,21 @@ describe("client/src/organism/OperatorsDos", () => { expect(ops.vars).toEqual([0, 1, 2, 3]); expect(ops.onOperator(0x04ffffff, 7)).toEqual(8); //v3=v3<=v3; expect(ops.vars).toEqual([0, 1, 2, 1]); + expect(ops.onOperator(0x046d3fff, 0)).toEqual(1); //v1=v2%v3; + expect(ops.vars).toEqual([0, 0, 2, 1]); + + expect(ops.onOperator(0x046c3fff, 0)).toEqual(1); //v1=v2+v3; + expect(ops.vars).toEqual([0, 3, 2, 1]); + expect(ops.onOperator(0x046c7fff, 0)).toEqual(1); //v1=v2-v3; + expect(ops.vars).toEqual([0, 1, 2, 1]); + expect(ops.onOperator(0x046cbfff, 0)).toEqual(1); //v1=v2*v3; + expect(ops.vars).toEqual([0, 2, 2, 1]); + ops.vars = [0, 1, 2, 4]; + expect(ops.onOperator(0x046cffff, 0)).toEqual(1); //v1=v2/v3; + expect(ops.vars).toEqual([0, .5, 2, 4]); + ops.vars = [0, 1, 2, 3]; + expect(ops.onOperator(0x046d3fff, 0)).toEqual(1); //v1=v2%v3; + expect(ops.vars).toEqual([0, 2, 2, 3]); }); it('Checking onOperator() with 4 bits per var', () => { @@ -211,6 +226,26 @@ describe("client/src/organism/OperatorsDos", () => { OConfig.codeBitsPerVar = bpv; ops1.destroy(); }); + + it("Checking overflows", () => { + const max = Number.MAX_VALUE; + + ops.vars = [0, 1, max, max]; + expect(ops.onOperator(0x046c3fff, 0)).toEqual(1); //v1=v2+v3; + expect(ops.vars).toEqual([0, max, max, max]); + ops.vars = [0, 1, -max, max]; + expect(ops.onOperator(0x046c7fff, 0)).toEqual(1); //v1=v2-v3; + expect(ops.vars).toEqual([0, -max, -max, max]); + ops.vars = [0, 1, max, max]; + expect(ops.onOperator(0x046cbfff, 0)).toEqual(1); //v1=v2*v3; + expect(ops.vars).toEqual([0, max, max, max]); + ops.vars = [0, 1, max, 0]; + expect(ops.onOperator(0x046cffff, 0)).toEqual(1); //v1=v2/v3; + expect(ops.vars).toEqual([0, max, max, 0]); + ops.vars = [0, 1, 2, 0]; + expect(ops.onOperator(0x046d3fff, 0)).toEqual(1); //v1=v2%v3; + expect(ops.vars).toEqual([0, 0, 2, 0]); + }); }); it("Checking onLookAt() in a complex way", () => { From 95d4c78d075347166d238d3b171d8feaa6375428 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 16:27:36 +0200 Subject: [PATCH 182/291] fixed broken onLookAt operator fixed few more tests #83 --- .../plugins/organisms/dos/Operators.js | 14 ++- .../plugins/organisms/dos/OperatorsSpec.js | 87 +++++++++++-------- .../plugins/organisms/dos/Organisms.js | 1 - 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 90b2d6b..6fc5da0 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -158,14 +158,12 @@ class OperatorsDos extends Operators { onLookAt(num, line, org) { const vars = this.vars; - let x = vars[Num.getVar1(num)]; - let y = vars[Num.getVar2(num)]; - - if (!IN_WORLD(x, y)) { - const ret = this._ret; - ret.ret = 0; - this.obs.fire(EVENTS.GET_ENERGY, org, x, y, ret); - vars[Num.getVar0(num)] = ret.ret; + const x = vars[Num.getVar1(num)]; + const y = vars[Num.getVar2(num)]; + + if (IN_WORLD(x, y)) { + this.obs.fire(EVENTS.GET_ENERGY, org, x, y, this._ret); + vars[Num.getVar0(num)] = this._ret.ret; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index f04dff9..5c64bfe 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -6,7 +6,7 @@ describe("client/src/organism/OperatorsDos", () => { let Observer = require('./../../../../../../common/src/Observer'); let EVENTS = require('./../../../../share/Events').EVENTS; let EVENT_AMOUNT = require('./../../../../share/Events').EVENT_AMOUNT; - //let Config = require('./../../../../share/Config').Config; + let Config = require('./../../../../share/Config').Config; let OrganismDos = require('./../../organisms/dos/Organism'); //let OEvents = require('./../../organisms/Organism').EVENTS; //let api = require('./../../../../share/Config').api; @@ -248,50 +248,61 @@ describe("client/src/organism/OperatorsDos", () => { }); }); - it("Checking onLookAt() in a complex way", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); + describe('onLookAt() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; + + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); + + it("Checking onLookAt() is found nothing", () => { + org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + expect(x).toBe(2); + expect(y).toBe(3); + ret.ret = 0; + }); + expect(ops.onLookAt(0x056fffff, 0, org)).toEqual(1); //v1=lookAt(v2,v3); + expect(ops.vars).toEqual([0,0,2,3]); + }); - expect(ops.onLookAt(0x041bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); + it("Checking onLookAt() looking outside of the world", () => { + ops.vars = [0, 1, 20, 30]; + expect(ops.onLookAt(0x056fffff, 0, org)).toEqual(1); //v1=lookAt(v2,v3); + expect(ops.vars).toEqual([0,0,20,30]); - obs.on(EVENTS.GET_ENERGY, (org, x, y, ret) => { - ret.ret = 7; - expect(x === 1 && y === 2).toEqual(true); + ops.vars = [0, 1, -20, -30]; + expect(ops.onLookAt(0x056fffff, 0, org)).toEqual(1); //v1=lookAt(v2,v3); + expect(ops.vars).toEqual([0,0,-20,-30]); }); - expect(ops.onLookAt(0x041bffff, 0, {}, 1)).toEqual(1);//v0=org.lookAt(v1,v2); - expect(ops.vars[0] === 7).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - obs.clear(); - obs.on(EVENTS.GET_ENERGY, (org, x, y, ret) => { - ret.ret = 8; - expect(x === 2 && y === 3).toEqual(true); + it('Checking onLookAt() found an energy', () => { + org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + expect(x).toBe(2); + expect(y).toBe(3); + ret.ret = 13; + }); + expect(ops.onLookAt(0x056fffff, 0, org)).toEqual(1); //v1=lookAt(v2,v3); + expect(ops.vars).toEqual([0,13,2,3]); }); - expect(ops.onLookAt(0x046fffff, 1, {}, 1)).toEqual(2);//v1=org.lookAt(v2,v3); - expect(ops.vars[0] === 7).toEqual(true); - expect(ops.vars[1] === 8).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - obs.clear(); - obs.on(EVENTS.GET_ENERGY, (org, x, y, ret) => { - ret.ret = 9; - expect(x === 3 && y === 3).toEqual(true); - }); - expect(ops.onLookAt(0x04ffffff, 3, {}, 1)).toEqual(4);//v3=org.lookAt(v3,v3); - expect(ops.vars[0] === 7).toEqual(true); - expect(ops.vars[1] === 8).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 9).toEqual(true); + it('Checking onLookAt() with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7], org); - obs.clear(); - ops.destroy(); + org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + expect(x).toBe(7); + expect(y).toBe(7); + ret.ret = 13; + }); + expect(ops1.onLookAt(0x056fffff, 0, org)).toEqual(1); //v6=lookAt(v15,v15); + expect(ops1.vars).toEqual([0,1,2,3,4,5,13,7,8,9,10,11,12,13,14,7]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); it("Checking onEatLeft() method", () => { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index ae0bdb1..27d9ad1 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -140,7 +140,6 @@ class Organisms extends BaseOrganisms { } _onGetEnergy(org, x, y, ret) { - if (x < 0 || y < 0 || !Number.isInteger(x) || !Number.isInteger(y)) {return} const posId = POSID(x, y); if (typeof(this.positions[posId]) === 'undefined') { From 9aaf55aec0a196b70bfdcbdbb26e723639567534 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 19:10:10 +0200 Subject: [PATCH 183/291] returned an ability to put energy outside - into the world fixed few more tests #83 --- .../src/manager/plugins/organisms/dos/Operators.js | 13 +++++-------- .../manager/plugins/organisms/dos/OperatorsSpec.js | 11 +++++++++++ .../src/manager/plugins/organisms/dos/Organisms.js | 8 ++++++-- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 6fc5da0..d01e96d 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -158,8 +158,8 @@ class OperatorsDos extends Operators { onLookAt(num, line, org) { const vars = this.vars; - const x = vars[Num.getVar1(num)]; - const y = vars[Num.getVar2(num)]; + const x = (vars[Num.getVar1(num)] + .5) << 0; + const y = (vars[Num.getVar2(num)] + .5) << 0; if (IN_WORLD(x, y)) { this.obs.fire(EVENTS.GET_ENERGY, org, x, y, this._ret); @@ -200,17 +200,14 @@ class OperatorsDos extends Operators { onCheckDown(num, line, org) {return this._checkAt(num, line, org, org.x, org.y + 1)} _checkAt(num, line, org, x, y) { - const ret = this._ret; - - ret.ret = 0; - this.obs.fire(EVENTS.CHECK_AT, x, y, ret); - this.vars[Num.getVar0(num)] = ret.ret; + this.obs.fire(EVENTS.CHECK_AT, x, y, this._ret); + this.vars[Num.getVar0(num)] = this._ret.ret; return ++line; } _eat(org, num, x, y) { const amount = this.vars[Num.getVar1(num)]; - if (amount <= 0) {return 0} + if (amount === 0) {return 0} const ret = this._ret; ret.ret = amount; diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 5c64bfe..7893a0f 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -303,6 +303,17 @@ describe("client/src/organism/OperatorsDos", () => { OConfig.codeBitsPerVar = bpv; ops1.destroy(); }); + + it('Checking onLookAt() with floating coordinates', () => { + org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + expect(x).toBe(0); + expect(y).toBe(4); + ret.ret = 13; + }); + ops.vars = [0, 1, .1, 3.6]; + expect(ops.onLookAt(0x056fffff, 0, org)).toEqual(1); //v1=lookAt(v2,v3); + expect(ops.vars).toEqual([0,13,.1,3.6]); + }); }); it("Checking onEatLeft() method", () => { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 27d9ad1..0b96fde 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -156,8 +156,9 @@ class Organisms extends BaseOrganisms { // eat less, big - more // const eat = ret.ret / ((OConfig.codeMaxSize / (org.vm.size || 1)) || 1); + let dir; - [x, y] = NORMALIZE_NO_DIR(x, y); + [x, y, dir] = NORMALIZE(x, y); const posId = POSID(x, y); if (typeof(positions[posId]) === 'undefined') { @@ -165,7 +166,10 @@ class Organisms extends BaseOrganisms { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); } else { - ret.ret = 0; + if (dir !== DIR.NO) {ret.ret = 0;return} + ret.ret = eat; + this.world.setDot(x, y, (-eat + .5) << 0); + this.parent.fire(EVENTS.EAT_ENERGY, eat); } } else { const victimOrg = positions[posId]; From e39e0f6c8e2361f637d364c05bdb5a7d1488dca8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 20:18:04 +0200 Subject: [PATCH 184/291] temporary commented checker operators fixed few more tests #83 --- .../plugins/organisms/dos/Code2String.js | 40 +-- .../plugins/organisms/dos/Operators.js | 31 +- .../plugins/organisms/dos/OperatorsSpec.js | 284 ++++-------------- .../plugins/organisms/dos/Organisms.js | 21 +- 4 files changed, 92 insertions(+), 284 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 4b2ec16..4bbb7ca 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -38,11 +38,11 @@ class Code2String { this._onFromMem.bind(this), this._onToMem.bind(this), this._onMyX.bind(this), - this._onMyY.bind(this), - this._onCheckLeft.bind(this), - this._onCheckRight.bind(this), - this._onCheckUp.bind(this), - this._onCheckDown.bind(this) + this._onMyY.bind(this) + // this._onCheckLeft.bind(this), + // this._onCheckRight.bind(this), + // this._onCheckUp.bind(this), + // this._onCheckDown.bind(this) ]; this._OPERATORS_CB_LEN = this._OPERATORS_CB.length; /** @@ -209,21 +209,21 @@ class Code2String { return `v${Num.getVar0(num)}=myY()`; } - _onCheckLeft(num) { - return `v${Num.getVar0(num)}=checkLeft()`; - } - - _onCheckRight(num) { - return `v${Num.getVar0(num)}=checkRight()`; - } - - _onCheckUp(num) { - return `v${Num.getVar0(num)}=checkUp()`; - } - - _onCheckDown(num) { - return `v${Num.getVar0(num)}=checkDown()`; - } + // _onCheckLeft(num) { + // return `v${Num.getVar0(num)}=checkLeft()`; + // } + // + // _onCheckRight(num) { + // return `v${Num.getVar0(num)}=checkRight()`; + // } + // + // _onCheckUp(num) { + // return `v${Num.getVar0(num)}=checkUp()`; + // } + // + // _onCheckDown(num) { + // return `v${Num.getVar0(num)}=checkDown()`; + // } /** * Returns offset for closing bracket of blocked operators like diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index d01e96d..2972d37 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -77,11 +77,11 @@ class OperatorsDos extends Operators { this.onFromMem.bind(this), this.onToMem.bind(this), this.onMyX.bind(this), - this.onMyY.bind(this), - this.onCheckLeft.bind(this), - this.onCheckRight.bind(this), - this.onCheckUp.bind(this), - this.onCheckDown.bind(this) + this.onMyY.bind(this) + //this.onCheckLeft.bind(this), + //this.onCheckRight.bind(this), + //this.onCheckUp.bind(this), + //this.onCheckDown.bind(this) ]; /** * {Object} Reusable object to pass it as a parameter to this.fire(..., ret) @@ -156,17 +156,12 @@ class OperatorsDos extends Operators { return ++line; } - onLookAt(num, line, org) { + onLookAt(num, line) { const vars = this.vars; const x = (vars[Num.getVar1(num)] + .5) << 0; const y = (vars[Num.getVar2(num)] + .5) << 0; - if (IN_WORLD(x, y)) { - this.obs.fire(EVENTS.GET_ENERGY, org, x, y, this._ret); - vars[Num.getVar0(num)] = this._ret.ret; - - return ++line; - } + if (IN_WORLD(x, y)) {return this._checkAt(num, line, x, y)} vars[Num.getVar0(num)] = 0; return ++line; @@ -194,13 +189,13 @@ class OperatorsDos extends Operators { onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; return ++line} onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; return ++line} - onCheckLeft(num, line, org) {return this._checkAt(num, line, org, org.x - 1, org.y)} - onCheckRight(num, line, org) {return this._checkAt(num, line, org, org.x + 1, org.y)} - onCheckUp(num, line, org) {return this._checkAt(num, line, org, org.x, org.y - 1)} - onCheckDown(num, line, org) {return this._checkAt(num, line, org, org.x, org.y + 1)} + // onCheckLeft(num, line, org) {return this._checkAt(num, line, org.x - 1, org.y)} + // onCheckRight(num, line, org) {return this._checkAt(num, line, org.x + 1, org.y)} + // onCheckUp(num, line, org) {return this._checkAt(num, line, org.x, org.y - 1)} + // onCheckDown(num, line, org) {return this._checkAt(num, line, org.x, org.y + 1)} - _checkAt(num, line, org, x, y) { - this.obs.fire(EVENTS.CHECK_AT, x, y, this._ret); + _checkAt(num, line, x, y) { + this.obs.fire(EVENTS.GET_ENERGY, x, y, this._ret); this.vars[Num.getVar0(num)] = this._ret.ret; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 7893a0f..62db938 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -258,7 +258,7 @@ describe("client/src/organism/OperatorsDos", () => { afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking onLookAt() is found nothing", () => { - org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + org.on(EVENTS.GET_ENERGY, (x, y, ret) => { expect(x).toBe(2); expect(y).toBe(3); ret.ret = 0; @@ -278,7 +278,7 @@ describe("client/src/organism/OperatorsDos", () => { }); it('Checking onLookAt() found an energy', () => { - org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + org.on(EVENTS.GET_ENERGY, (x, y, ret) => { expect(x).toBe(2); expect(y).toBe(3); ret.ret = 13; @@ -292,7 +292,7 @@ describe("client/src/organism/OperatorsDos", () => { OConfig.codeBitsPerVar = 4; let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7], org); - org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + org.on(EVENTS.GET_ENERGY, (x, y, ret) => { expect(x).toBe(7); expect(y).toBe(7); ret.ret = 13; @@ -305,7 +305,7 @@ describe("client/src/organism/OperatorsDos", () => { }); it('Checking onLookAt() with floating coordinates', () => { - org.on(EVENTS.GET_ENERGY, (o, x, y, ret) => { + org.on(EVENTS.GET_ENERGY, (x, y, ret) => { expect(x).toBe(0); expect(y).toBe(4); ret.ret = 13; @@ -316,65 +316,65 @@ describe("client/src/organism/OperatorsDos", () => { }); }); - it("Checking onEatLeft() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:4, y:5, energy:0}; + describe('onEatLeft() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 1).toEqual(true); - ret.ret = 5; - expect(x === 3 && y === 5).toEqual(true); - }); - expect(ops.onEatLeft(0x051fffff, 0, org, 1)).toEqual(1); // v0=org.eatLeft(v1); - expect(ops.vars[0] === 5).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatLeft() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:5, y:6, energy:0}; + it("Checking eating nothing", () => { + ops.vars = [1, 0, 1, 2]; + expect(ops.onEatLeft(0x061fffff, 0, org)).toEqual(1); // v0=eatLeft(v1); + expect(ops.vars).toEqual([0, 0, 1, 2]); + }); + it("Checking eating nothing 2", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 0; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatLeft(0x061fffff, 0, org)).toEqual(1); // v0=eatLeft(v1); + expect(ops.vars).toEqual([0,1,2,3]); + }); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 2).toEqual(true); - ret.ret = 5; - expect(x === 4 && y === 6).toEqual(true); + it("Checking eating energy", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatLeft(0x061fffff, 0, org)).toEqual(1); // v0=eatLeft(v1); + expect(ops.vars).toEqual([5,1,2,3]); }); - expect(ops.onEatLeft(0x056fffff, 0, org, 1)).toEqual(1); // v1=org.eatLeft(v2); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 5).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatLeft() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:3, y:4, energy:0}; + it('Checking eating with 3bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7], org); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 3).toEqual(true); - ret.ret = 1; - expect(x === 2 && y === 4).toEqual(true); - }); - expect(ops.onEatLeft(0x05ffffff, 0, org, 1)).toEqual(1); // v3=org.eatLeft(v3); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.energy === 1).toEqual(true); + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(4); + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops1.onEatLeft(0x0633ffff, 0, org)).toEqual(1); // v1=eatLeft(v4); + expect(ops1.vars).toEqual([0,5,2,3,4,5,6,7]); - obs.clear(); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }) }); it("Checking onEatRight() method", () => { @@ -908,176 +908,4 @@ describe("client/src/organism/OperatorsDos", () => { ops.destroy(); }); - - it("Checking onCheckLeft() method", () => { - let org = new Observer(EVENT_AMOUNT); - let obs = new Observer(); - let ops = new OperatorsDos([], [1, 7, 2, 3], obs); - - org.x = 1; - org.y = 2; - - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 0 && y === 2).toEqual(true); - ret.ret = 0; - }); - expect(ops.onCheckLeft(0x111fffff, 0, org)).toEqual(1); // v0=org.onCheckLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 0 && y === 2).toEqual(true); - ret.ret = 1; - }); - expect(ops.onCheckLeft(0x116fffff, 0, org)).toEqual(1); // v1=org.onCheckLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 0 && y === 2).toEqual(true); - ret.ret = 2; - }); - expect(ops.onCheckLeft(0x11ffffff, 0, org)).toEqual(1); // v3=org.onCheckLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 2).toEqual(true); - - ops.destroy(); - }); - - it("Checking onCheckRight() method", () => { - let org = new Observer(EVENT_AMOUNT); - let obs = new Observer(); - let ops = new OperatorsDos([], [1, 7, 2, 3], obs); - - org.x = 1; - org.y = 2; - - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 2 && y === 2).toEqual(true); - ret.ret = 0; - }); - expect(ops.onCheckRight(0x121fffff, 0, org)).toEqual(1); // v0=org.onCheckRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 2 && y === 2).toEqual(true); - ret.ret = 1; - }); - expect(ops.onCheckRight(0x126fffff, 0, org)).toEqual(1); // v1=org.onCheckRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 2 && y === 2).toEqual(true); - ret.ret = 2; - }); - expect(ops.onCheckRight(0x12ffffff, 0, org)).toEqual(1); // v3=org.onCheckRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 2).toEqual(true); - - ops.destroy(); - }); - - it("Checking onCheckUp() method", () => { - let org = new Observer(EVENT_AMOUNT); - let obs = new Observer(); - let ops = new OperatorsDos([], [1, 7, 2, 3], obs); - - org.x = 1; - org.y = 2; - - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 1).toEqual(true); - ret.ret = 0; - }); - expect(ops.onCheckUp(0x131fffff, 0, org)).toEqual(1); // v0=org.onCheckUp(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 1).toEqual(true); - ret.ret = 1; - }); - expect(ops.onCheckUp(0x136fffff, 0, org)).toEqual(1); // v1=org.onCheckUp(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 1).toEqual(true); - ret.ret = 2; - }); - expect(ops.onCheckUp(0x13ffffff, 0, org)).toEqual(1); // v3=org.onCheckUp(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 2).toEqual(true); - - ops.destroy(); - }); - - it("Checking onCheckDown() method", () => { - let org = new Observer(EVENT_AMOUNT); - let obs = new Observer(); - let ops = new OperatorsDos([], [1, 7, 2, 3], obs); - - org.x = 1; - org.y = 2; - - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 3).toEqual(true); - ret.ret = 0; - }); - expect(ops.onCheckDown(0x141fffff, 0, org)).toEqual(1); // v0=org.onCheckDown(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 3).toEqual(true); - ret.ret = 1; - }); - expect(ops.onCheckDown(0x146fffff, 0, org)).toEqual(1); // v1=org.onCheckDown(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - - org.clear(); - org.on(EVENTS.CHECK_AT, (x, y, ret) => { - expect(x === 1 && y === 3).toEqual(true); - ret.ret = 2; - }); - expect(ops.onCheckDown(0x14ffffff, 0, org)).toEqual(1); // v3=org.onCheckDown(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 2).toEqual(true); - - ops.destroy(); - }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 0b96fde..de0c1e3 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -97,7 +97,6 @@ class Organisms extends BaseOrganisms { org.on(EVENTS.GET_ENERGY, this._onGetEnergy.bind(this)); org.on(EVENTS.EAT, this._onEat.bind(this)); org.on(EVENTS.STEP, this._onStep.bind(this)); - org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); } /** @@ -139,7 +138,7 @@ class Organisms extends BaseOrganisms { return true; } - _onGetEnergy(org, x, y, ret) { + _onGetEnergy(x, y, ret) { const posId = POSID(x, y); if (typeof(this.positions[posId]) === 'undefined') { @@ -156,17 +155,14 @@ class Organisms extends BaseOrganisms { // eat less, big - more // const eat = ret.ret / ((OConfig.codeMaxSize / (org.vm.size || 1)) || 1); - let dir; - - [x, y, dir] = NORMALIZE(x, y); + [x, y] = NORMALIZE_NO_DIR(x, y); + const posId = POSID(x, y); - const posId = POSID(x, y); if (typeof(positions[posId]) === 'undefined') { if (eat > 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); } else { - if (dir !== DIR.NO) {ret.ret = 0;return} ret.ret = eat; this.world.setDot(x, y, (-eat + .5) << 0); this.parent.fire(EVENTS.EAT_ENERGY, eat); @@ -252,17 +248,6 @@ class Organisms extends BaseOrganisms { org.energy -= energy; } } - - _onCheckAt(x, y, ret) { - const org = this.positions[POSID(x, y)]; - - if (typeof(org) === 'undefined') { - [x, y] = NORMALIZE_NO_DIR(x, y); - ret.ret = this.world.getDot(x, y); - } else { - ret.ret = org.energy; - } - } } module.exports = Organisms; \ No newline at end of file From f19eb54cee3d72d99f4a6a2d104debf6dd9b8fd8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 17 Feb 2018 21:07:24 +0200 Subject: [PATCH 185/291] fixed new tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 312 +++++++++--------- 1 file changed, 156 insertions(+), 156 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 62db938..5595c23 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -377,187 +377,187 @@ describe("client/src/organism/OperatorsDos", () => { }) }); - it("Checking onEatRight() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:4, y:5, energy:0}; + describe('onEatRight() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 1).toEqual(true); - ret.ret = 5; - expect(x === 5 && y === 5).toEqual(true); - }); - expect(ops.onEatRight(0x061fffff, 0, org, 1)).toEqual(1); // v0=org.eatRight(v1); - expect(ops.vars[0] === 5).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatRight() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:5, y:6, energy:0}; + it("Checking eating nothing", () => { + ops.vars = [1, 0, 1, 2]; + expect(ops.onEatRight(0x071fffff, 0, org)).toEqual(1); // v0=eatRight(v1); + expect(ops.vars).toEqual([0, 0, 1, 2]); + }); + it("Checking eating nothing 2", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(3); + expect(y).toBe(3); + ret.ret = 0; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatRight(0x071fffff, 0, org)).toEqual(1); // v0=eatRight(v1); + expect(ops.vars).toEqual([0,1,2,3]); + }); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 2).toEqual(true); - ret.ret = 5; - expect(x === 6 && y === 6).toEqual(true); + it("Checking eating energy", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(3); + expect(y).toBe(3); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatRight(0x071fffff, 0, org)).toEqual(1); // v0=eatRight(v1); + expect(ops.vars).toEqual([5,1,2,3]); }); - expect(ops.onEatRight(0x066fffff, 0, org, 1)).toEqual(1); // v1=org.eatRight(v2); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 5).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatRight() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:3, y:4, energy:0}; + it('Checking eating with 3bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7], org); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 3).toEqual(true); - ret.ret = 1; - expect(x === 4 && y === 4).toEqual(true); - }); - expect(ops.onEatRight(0x06ffffff, 0, org, 1)).toEqual(1); // v3=org.eatRight(v3); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.energy === 1).toEqual(true); + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(4); + expect(x).toBe(3); + expect(y).toBe(3); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops1.onEatRight(0x0733ffff, 0, org)).toEqual(1); // v1=eatRight(v4); + expect(ops1.vars).toEqual([0,5,2,3,4,5,6,7]); - obs.clear(); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }) }); - it("Checking onEatUp() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:4, y:5, energy:0}; + describe('onEatUp() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 1).toEqual(true); - ret.ret = 5; - expect(x === 4 && y === 4).toEqual(true); - }); - expect(ops.onEatUp(0x071fffff, 0, org, 1)).toEqual(1); // v0=org.onEatUp(v1); - expect(ops.vars[0] === 5).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatUp() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:5, y:6, energy:0}; + it("Checking eating nothing", () => { + ops.vars = [1, 0, 1, 2]; + expect(ops.onEatUp(0x081fffff, 0, org)).toEqual(1); // v0=eatUp(v1); + expect(ops.vars).toEqual([0, 0, 1, 2]); + }); + it("Checking eating nothing 2", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 0; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatUp(0x081fffff, 0, org)).toEqual(1); // v0=eatUp(v1); + expect(ops.vars).toEqual([0,1,2,3]); + }); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 2).toEqual(true); - ret.ret = 5; - expect(x === 5 && y === 5).toEqual(true); + it("Checking eating energy", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatUp(0x081fffff, 0, org)).toEqual(1); // v0=eatUp(v1); + expect(ops.vars).toEqual([5,1,2,3]); }); - expect(ops.onEatUp(0x076fffff, 0, org, 1)).toEqual(1); // v1=org.onEatUp(v2); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 5).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatUp() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:3, y:4, energy:0}; + it('Checking eating with 3bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7], org); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 3).toEqual(true); - ret.ret = 1; - expect(x === 3 && y === 3).toEqual(true); - }); - expect(ops.onEatUp(0x07ffffff, 0, org, 1)).toEqual(1); // v3=org.onEatUp(v3); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.energy === 1).toEqual(true); + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(4); + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops1.onEatUp(0x0833ffff, 0, org)).toEqual(1); // v1=eatUp(v4); + expect(ops1.vars).toEqual([0,5,2,3,4,5,6,7]); - obs.clear(); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }) }); - it("Checking onEatDown() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:4, y:5, energy:0}; + describe('onEatDown() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 1).toEqual(true); - ret.ret = 5; - expect(x === 4 && y === 6).toEqual(true); - }); - expect(ops.onEatDown(0x081fffff, 0, org, 1)).toEqual(1); // v0=org.onEatDown(v1); - expect(ops.vars[0] === 5).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatDown() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:5, y:6, energy:0}; + it("Checking eating nothing", () => { + ops.vars = [1, 0, 1, 2]; + expect(ops.onEatDown(0x091fffff, 0, org)).toEqual(1); // v0=eatDown(v1); + expect(ops.vars).toEqual([0, 0, 1, 2]); + }); + it("Checking eating nothing 2", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(2); + expect(y).toBe(4); + ret.ret = 0; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatDown(0x091fffff, 0, org)).toEqual(1); // v0=eatDown(v1); + expect(ops.vars).toEqual([0,1,2,3]); + }); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 2).toEqual(true); - ret.ret = 5; - expect(x === 5 && y === 7).toEqual(true); + it("Checking eating energy", () => { + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(1); + expect(x).toBe(2); + expect(y).toBe(4); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops.onEatDown(0x091fffff, 0, org)).toEqual(1); // v0=eatDown(v1); + expect(ops.vars).toEqual([5,1,2,3]); }); - expect(ops.onEatDown(0x086fffff, 0, org, 1)).toEqual(1); // v1=org.onEatDown(v2); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 5).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.energy === 5).toEqual(true); - obs.clear(); - ops.destroy(); - }); - it("Checking onEatDown() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [1, 1, 2, 3], obs); - let org = {x:3, y:4, energy:0}; + it('Checking eating with 3bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 3; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7], org); - obs.on(EVENTS.EAT, (org, x, y, ret) => { - expect(ret.ret === 3).toEqual(true); - ret.ret = 1; - expect(x === 3 && y === 5).toEqual(true); - }); - expect(ops.onEatDown(0x08ffffff, 0, org, 1)).toEqual(1); // v3=org.onEatDown(v3); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.energy === 1).toEqual(true); + org.on(EVENTS.EAT, (org, x, y, ret) => { + expect(ret.ret).toBe(4); + expect(x).toBe(2); + expect(y).toBe(4); + ret.ret = 5; + }); + org.x = 2; + org.y = 3; + expect(ops1.onEatDown(0x0933ffff, 0, org)).toEqual(1); // v1=eatDown(v4); + expect(ops1.vars).toEqual([0,5,2,3,4,5,6,7]); - obs.clear(); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }) }); it("Checking onStepLeft() method", () => { From ac13cb3f582a91a45f7d09bb4aff9c3ec4cc9cf0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 00:45:43 +0200 Subject: [PATCH 186/291] fixed an issue with disappeared energy fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 167 ++++++------------ .../plugins/organisms/dos/Organisms.js | 2 +- 2 files changed, 52 insertions(+), 117 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 5595c23..d2a1107 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -560,133 +560,68 @@ describe("client/src/organism/OperatorsDos", () => { }) }); - it("Checking onStepLeft() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 2; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); - }); - expect(ops.onStepLeft(0x091fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 2 && org.y === 4).toEqual(true); + describe('onStepLeft() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - obs.clear(); - ops.destroy(); - }); - it("Checking onStepLeft() method with no free space on the left", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); + it("Checking step left", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); + }); + expect(ops.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v0=stepLeft(); + expect(ops.vars).toEqual([2,1,2,3]); + expect(org.x).toBe(2); + expect(org.y).toBe(4); }); - expect(ops.onStepLeft(0x091fffff, 0, org, 1)).toEqual(1); // v0=org.stepLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); - - obs.clear(); - ops.destroy(); - }); - it("Checking onStepLeft() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 2; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); + it("Checking step left() with no free space on the left", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 0; + ret.x = x1; + ret.y = y1; + expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); + }); + expect(ops.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v0=stepLeft(); + expect(ops.vars).toEqual([3,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(4); }); - expect(ops.onStepLeft(0x096fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 2 && org.y === 4).toEqual(true); - //expect(ops.onStepLeft(0x08ffffff), 0, org, 1)).toEqual() // v3=org.stepLeft(); - - obs.clear(); - ops.destroy(); - }); - it("Checking onStepLeft() method 2 with no free space on the left", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); - }); - expect(ops.onStepLeft(0x096fffff, 0, org, 1)).toEqual(1); // v1=org.stepLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); + it("Checking step left with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); - obs.clear(); - ops.destroy(); - }); - it("Checking onStepLeft() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); + }); + expect(ops1.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v1=stepLeft(); + expect(ops1.vars).toEqual([0,2,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + expect(org.x).toBe(2); + expect(org.y).toBe(4); - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 2; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); }); - expect(ops.onStepLeft(0x09ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.x === 2 && org.y === 4).toEqual(true); - - obs.clear(); - ops.destroy(); }); - it("Checking onStepLeft() method 3 with no free space on the left", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toEqual(true); - }); - expect(ops.onStepLeft(0x09ffffff, 0, org, 1)).toEqual(1); // v3=org.stepLeft(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); - obs.clear(); - ops.destroy(); - }); it("Checking onStepRight() method", () => { let obs = new Observer(EVENT_AMOUNT); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index de0c1e3..326c0dd 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -164,7 +164,7 @@ class Organisms extends BaseOrganisms { this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); } else { ret.ret = eat; - this.world.setDot(x, y, (-eat + .5) << 0); + this.world.setDot(x, y, ((-eat + .5) << 0) + this.world.getDot(x, y)); this.parent.fire(EVENTS.EAT_ENERGY, eat); } } else { From 328d72ce6a821976faca1307a119c8588ef06813 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 13:00:53 +0200 Subject: [PATCH 187/291] onCheckXXX() changed to return object type fixed few more tests #83 --- .../src/manager/plugins/organisms/Config.js | 2 +- .../plugins/organisms/dos/Code2String.js | 40 ++-- .../plugins/organisms/dos/Operators.js | 26 +-- .../plugins/organisms/dos/OperatorsSpec.js | 174 ++++++------------ .../plugins/organisms/dos/Organisms.js | 33 +++- client/src/share/Config.js | 4 +- 6 files changed, 117 insertions(+), 162 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 62db562..be5173c 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -128,7 +128,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 2000, + orgMaxOrgs: 3000, /** * {Number} Amount of organisms we have to create on program start */ diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 4bbb7ca..4b2ec16 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -38,11 +38,11 @@ class Code2String { this._onFromMem.bind(this), this._onToMem.bind(this), this._onMyX.bind(this), - this._onMyY.bind(this) - // this._onCheckLeft.bind(this), - // this._onCheckRight.bind(this), - // this._onCheckUp.bind(this), - // this._onCheckDown.bind(this) + this._onMyY.bind(this), + this._onCheckLeft.bind(this), + this._onCheckRight.bind(this), + this._onCheckUp.bind(this), + this._onCheckDown.bind(this) ]; this._OPERATORS_CB_LEN = this._OPERATORS_CB.length; /** @@ -209,21 +209,21 @@ class Code2String { return `v${Num.getVar0(num)}=myY()`; } - // _onCheckLeft(num) { - // return `v${Num.getVar0(num)}=checkLeft()`; - // } - // - // _onCheckRight(num) { - // return `v${Num.getVar0(num)}=checkRight()`; - // } - // - // _onCheckUp(num) { - // return `v${Num.getVar0(num)}=checkUp()`; - // } - // - // _onCheckDown(num) { - // return `v${Num.getVar0(num)}=checkDown()`; - // } + _onCheckLeft(num) { + return `v${Num.getVar0(num)}=checkLeft()`; + } + + _onCheckRight(num) { + return `v${Num.getVar0(num)}=checkRight()`; + } + + _onCheckUp(num) { + return `v${Num.getVar0(num)}=checkUp()`; + } + + _onCheckDown(num) { + return `v${Num.getVar0(num)}=checkDown()`; + } /** * Returns offset for closing bracket of blocked operators like diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 2972d37..c50ddef 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -77,11 +77,11 @@ class OperatorsDos extends Operators { this.onFromMem.bind(this), this.onToMem.bind(this), this.onMyX.bind(this), - this.onMyY.bind(this) - //this.onCheckLeft.bind(this), - //this.onCheckRight.bind(this), - //this.onCheckUp.bind(this), - //this.onCheckDown.bind(this) + this.onMyY.bind(this), + this.onCheckLeft.bind(this), + this.onCheckRight.bind(this), + this.onCheckUp.bind(this), + this.onCheckDown.bind(this) ]; /** * {Object} Reusable object to pass it as a parameter to this.fire(..., ret) @@ -161,7 +161,11 @@ class OperatorsDos extends Operators { const x = (vars[Num.getVar1(num)] + .5) << 0; const y = (vars[Num.getVar2(num)] + .5) << 0; - if (IN_WORLD(x, y)) {return this._checkAt(num, line, x, y)} + if (IN_WORLD(x, y)) { + this.obs.fire(EVENTS.GET_ENERGY, x, y, this._ret); + this.vars[Num.getVar0(num)] = this._ret.ret; + return ++line; + } vars[Num.getVar0(num)] = 0; return ++line; @@ -189,13 +193,13 @@ class OperatorsDos extends Operators { onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; return ++line} onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; return ++line} - // onCheckLeft(num, line, org) {return this._checkAt(num, line, org.x - 1, org.y)} - // onCheckRight(num, line, org) {return this._checkAt(num, line, org.x + 1, org.y)} - // onCheckUp(num, line, org) {return this._checkAt(num, line, org.x, org.y - 1)} - // onCheckDown(num, line, org) {return this._checkAt(num, line, org.x, org.y + 1)} + onCheckLeft(num, line, org) {return this._checkAt(num, line, org.x - 1, org.y)} + onCheckRight(num, line, org) {return this._checkAt(num, line, org.x + 1, org.y)} + onCheckUp(num, line, org) {return this._checkAt(num, line, org.x, org.y - 1)} + onCheckDown(num, line, org) {return this._checkAt(num, line, org.x, org.y + 1)} _checkAt(num, line, x, y) { - this.obs.fire(EVENTS.GET_ENERGY, x, y, this._ret); + this.obs.fire(EVENTS.CHECK_AT, x, y, this._ret); this.vars[Num.getVar0(num)] = this._ret.ret; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index d2a1107..4da0809 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -584,7 +584,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(org.y).toBe(4); }); - it("Checking step left() with no free space on the left", () => { + it("Checking step left with no free space on the left", () => { org.x = 3; org.y = 4; org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { @@ -622,132 +622,66 @@ describe("client/src/organism/OperatorsDos", () => { }); }); + describe('onStepRight() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - it("Checking onStepRight() method", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 4; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); + it("Checking step right", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); + }); + expect(ops.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v0=stepRight(); + expect(ops.vars).toEqual([4,1,2,3]); + expect(org.x).toBe(4); + expect(org.y).toBe(4); }); - expect(ops.onStepRight(0x0a1fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 4 && org.y === 4).toEqual(true); - obs.clear(); - ops.destroy(); - }); - it("Checking onStepRight() method with no free space on the right", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); - }); - expect(ops.onStepRight(0x0a1fffff, 0, org, 1)).toEqual(1); // v0=org.stepRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); - - obs.clear(); - ops.destroy(); - }); - it("Checking onStepRight() method 2", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 4; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); - }); - expect(ops.onStepRight(0x0a6fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 4 && org.y === 4).toEqual(true); - - obs.clear(); - ops.destroy(); - }); - it("Checking onStepRight() method 2 with no free space on the left", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); - }); - expect(ops.onStepRight(0x0a6fffff, 0, org, 1)).toEqual(1); // v1=org.stepRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 0).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); + it("Checking step right with no free space on the left", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 0; + ret.x = x1; + ret.y = y1; + expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); + }); + expect(ops.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v0=stepRight(); + expect(ops.vars).toEqual([3,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(4); + }); - obs.clear(); - ops.destroy(); - }); - it("Checking onStepRight() method 3", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = 4; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); - }); - expect(ops.onStepRight(0x0affffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - expect(org.x === 4 && org.y === 4).toEqual(true); + it("Checking step right with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); - obs.clear(); - ops.destroy(); - }); - it("Checking onStepRight() method 3 with no free space on the left", () => { - let obs = new Observer(EVENT_AMOUNT); - let ops = new OperatorsDos([], [0, 1, 2, 3], obs); - let org = {x:3, y:4}; - - obs.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = 3; - ret.y = 4; - expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toEqual(true); - }); - expect(ops.onStepRight(0x0affffff, 0, org, 1)).toEqual(1); // v3=org.stepRight(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 0).toEqual(true); - expect(org.x === 3 && org.y === 4).toEqual(true); + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); + }); + expect(ops1.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v1=stepRight(); + expect(ops1.vars).toEqual([0,4,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + expect(org.x).toBe(4); + expect(org.y).toBe(4); - obs.clear(); - ops.destroy(); + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); it("Checking onFromMem() method", () => { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 326c0dd..9dbbd5b 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -10,13 +10,19 @@ * * @author flatline */ -const BaseOrganisms = require('./../Organisms'); -const Organism = require('./Organism'); -const Config = require('./../../../../share/Config').Config; -const OConfig = require('./../Config'); -const EVENTS = require('./../../../../share/Events').EVENTS; -const Helper = require('./../../../../../../common/src/Helper'); -const DIR = require('./../../../../../../common/src/Directions').DIR; +const BaseOrganisms = require('./../Organisms'); +const Organism = require('./Organism'); +const Config = require('./../../../../share/Config').Config; +const OConfig = require('./../Config'); +const EVENTS = require('./../../../../share/Events').EVENTS; +const Helper = require('./../../../../../../common/src/Helper'); +const DIR = require('./../../../../../../common/src/Directions').DIR; +/** + * {Number} World object types + */ +const EMPTY = 0; +const ENERGY = 1; +const ORGANISM = 2; /** * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.normalize() @@ -27,7 +33,7 @@ const NORMALIZE_NO_DIR = Helper.normalizeNoDir; * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.posId() */ -const POSID = Helper.posId; +const POSID = Helper.posId; class Organisms extends BaseOrganisms { constructor(manager) { @@ -97,6 +103,7 @@ class Organisms extends BaseOrganisms { org.on(EVENTS.GET_ENERGY, this._onGetEnergy.bind(this)); org.on(EVENTS.EAT, this._onEat.bind(this)); org.on(EVENTS.STEP, this._onStep.bind(this)); + org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); } /** @@ -224,6 +231,16 @@ class Organisms extends BaseOrganisms { ret.ret = +this.move(x1, y1, x2, y2, org); } + _onCheckAt(x, y, ret) { + [x, y] = NORMALIZE_NO_DIR(x, y); + + if (typeof(this.parent.positions[POSID(x, y)]) === 'undefined') { + ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; + } else { + ret.ret = ORGANISM; + } + } + /** * Is called if organism step in from the server or other client (Manager/World). * If step in position is not free or maximum organisms are in the world, then diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 00f2f4a..5d9988e 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -52,11 +52,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920, + worldWidth: 1920 * 2, /** * {Number} World height */ - worldHeight: 1080, + worldHeight: 1080 * 2, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 From 9aa928a68dbc25d9ffbf5de3c13214cd53607077 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 13:29:13 +0200 Subject: [PATCH 188/291] after death, organism leave an energy if it's more then zero fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 64 ++++++++++++++++++- .../plugins/organisms/dos/Organisms.js | 8 +++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 4da0809..a9676f6 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -646,7 +646,7 @@ describe("client/src/organism/OperatorsDos", () => { expect(org.y).toBe(4); }); - it("Checking step right with no free space on the left", () => { + it("Checking step right with no free space on the right", () => { org.x = 3; org.y = 4; org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { @@ -684,6 +684,68 @@ describe("client/src/organism/OperatorsDos", () => { }); }); + describe('onStepUp() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; + + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); + + it("Checking step up", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); + }); + expect(ops.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v0=stepUp(); + expect(ops.vars).toEqual([3,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(3); + }); + + it("Checking step up with no free space on above", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 0; + ret.x = x1; + ret.y = y1; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); + }); + expect(ops.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v0=stepUp(); + expect(ops.vars).toEqual([4,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(4); + }); + + it("Checking step up with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); + }); + expect(ops1.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v1=stepUp(); + expect(ops1.vars).toEqual([0,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + expect(org.x).toBe(3); + expect(org.y).toBe(3); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + }); + it("Checking onFromMem() method", () => { let org = {mem: [1,2,3]}; let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 9dbbd5b..1bb7144 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -12,6 +12,7 @@ */ const BaseOrganisms = require('./../Organisms'); const Organism = require('./Organism'); +const OEVENTS = require('./../Organism').EVENTS; const Config = require('./../../../../share/Config').Config; const OConfig = require('./../Config'); const EVENTS = require('./../../../../share/Events').EVENTS; @@ -104,6 +105,7 @@ class Organisms extends BaseOrganisms { org.on(EVENTS.EAT, this._onEat.bind(this)); org.on(EVENTS.STEP, this._onStep.bind(this)); org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); + org.on(OEVENTS.DESTROY, this._onOrgDestroy.bind(this)); } /** @@ -241,6 +243,12 @@ class Organisms extends BaseOrganisms { } } + _onOrgDestroy(org) { + if (org.energy > 0) { + this.parent.world.setDot(org.x, org.y, org.energy); + } + } + /** * Is called if organism step in from the server or other client (Manager/World). * If step in position is not free or maximum organisms are in the world, then From a62b14db8728cdd2f08f53f4ba3b7e7ece793bdd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 16:42:26 +0200 Subject: [PATCH 189/291] memory operations work in two modes: from variable and by constant fixed few more tests #83 --- .../src/manager/plugins/organisms/Mutator.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 2 +- .../plugins/organisms/dos/Code2String.js | 12 +- .../plugins/organisms/dos/Operators.js | 16 ++- .../plugins/organisms/dos/OperatorsSpec.js | 126 ++++++++++++++---- .../plugins/organisms/dos/Organisms.js | 4 +- 6 files changed, 126 insertions(+), 36 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index dfab395..55bf1ed 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -120,7 +120,7 @@ class Mutator { const probIndex = Helper.probIndex; const mTypes = this._MUTATION_TYPES; const maxSize = OConfig.codeMaxSize; - let mutations = Math.round(vm.size * org.mutationPercent) || 1; + let mutations = ((vm.size * org.mutationPercent + .5) << 0) || 1; let type; for (let i = 0; i < mutations; i++) { diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 41d2843..14f9da0 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -247,7 +247,7 @@ class Organism extends Observer { _updateColor(changes) { this._colorIndex += (changes - this._changes); - this._color = Organism._getColor(Math.round(this._colorIndex / Num.MAX_BITS)); + this._color = Organism._getColor((this._colorIndex / Num.MAX_BITS + .5) << 0); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 4b2ec16..013efb2 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -194,11 +194,19 @@ class Code2String { } _onFromMem(num) { - return `v${Num.getVar0(num)}=fromMem(${Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; + if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { + return `v${Num.getVar0(num)}=fromMem(v${Num.getVar1(num)})`; + } + + const offs = Num.getBits(num, this._BITS_AFTER_TWO_VARS + 1, OConfig.orgMemBits); + return `v${Num.getVar0(num)}=fromMem(${offs})`; } _onToMem(num) { - return `toMem(v${Num.getVar0(num)},${Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)})`; + if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { + return `toMem(v${Num.getVar0(num)},v${Num.getVar1(num)})`; + } + return `toMem(v${Num.getVar0(num)},${Num.getBits(num, this._BITS_AFTER_TWO_VARS, OConfig.orgMemBits)})`; } _onMyX(num) { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index c50ddef..304604c 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -182,11 +182,23 @@ class OperatorsDos extends Operators { onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} onFromMem(num, line, org) { - this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)]; + if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { + const offs = (this.vars[Num.getVar1(num)] + .5) << 0; + this.vars[Num.getVar0(num)] = org.mem[offs >= org.mem.length || offs < 0 ? 0 : offs]; + return ++line; + } + + this.vars[Num.getVar0(num)] = org.mem[Num.getBits(num, this._BITS_AFTER_TWO_VARS + 1, OConfig.orgMemBits)]; return ++line; } onToMem(num, line, org) { - org.mem[Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; + if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { + const offs = (this.vars[Num.getVar0(num)] + .5) << 0; + org.mem[offs >= org.mem.length || offs < 0 ? 0 : offs] = this.vars[Num.getVar1(num)]; + return ++line; + } + + org.mem[Num.getBits(num, this._BITS_AFTER_TWO_VARS + 1, OConfig.orgMemBits)] = this.vars[Num.getVar0(num)]; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index a9676f6..451d262 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -746,39 +746,109 @@ describe("client/src/organism/OperatorsDos", () => { }); }); - it("Checking onFromMem() method", () => { - let org = {mem: [1,2,3]}; - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + describe('onStepDown() method', () => { + let org; + let ops; + const w = Config.worldWidth; + const h = Config.worldHeight; - expect(ops.onFromMem(0x0d1fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); - expect(ops.vars[0] === 3).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onFromMem(0x0d6fffff, 1, org, 2)).toEqual(2); //v1=org.fromMem(); - expect(ops.vars[0] === 3).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onFromMem(0x0dffffff, 2, org, 3)).toEqual(3); //v3=org.fromMem(); - expect(ops.vars[0] === 3).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); - ops.destroy(); + it("Checking step down", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); + }); + expect(ops.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v0=stepDown(); + expect(ops.vars).toEqual([5,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(5); + }); + + it("Checking step down with no free space below", () => { + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 0; + ret.x = x1; + ret.y = y1; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); + }); + expect(ops.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v0=stepDown(); + expect(ops.vars).toEqual([4,1,2,3]); + expect(org.x).toBe(3); + expect(org.y).toBe(4); + }); + + it("Checking step down with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.x = 3; + org.y = 4; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { + ret.ret = 1; + ret.x = x2; + ret.y = y2; + expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); + }); + expect(ops1.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v1=stepDown(); + expect(ops1.vars).toEqual([0,5,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + expect(org.x).toBe(3); + expect(org.y).toBe(5); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); - it("Checking onFromMem() method without memory", () => { - let org = {mem: []}; - let ops = new OperatorsDos([], [7, 1, 2, 3], new Observer()); - expect(ops.onFromMem(0x0d1fffff, 0, org, 1)).toEqual(1); //v0=org.fromMem(); - expect(ops.vars[0] === 0).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); + describe('onFromMem() method', () => { + let org; + let ops; + const mbits = OConfig.orgMemBits; + OConfig.orgMemBits = 2; - ops.destroy(); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + afterAll(() => OConfig.orgMemBits = mbits); + + it("Checking getting value by constant", () => { + org.mem.splice(0, org.mem.length, ...[1,2,3,4]); + expect(ops.onFromMem(0x0b10ffff, 0, org)).toEqual(1); //v0=fromMem(); + expect(ops.vars).toEqual([1,1,2,3]); + + org.mem.splice(0, org.mem.length, ...[0,1,2,3]); + expect(ops.onFromMem(0x0b50ffff, 0, org)).toEqual(1); //v1=fromMem(); + expect(ops.vars).toEqual([1,0,2,3]); + }); + + it("Checking getting value by variable value", () => { + org.mem.splice(0, org.mem.length, ...[1,2,3,4]); + expect(ops.onFromMem(0x0b1fffff, 0, org)).toEqual(1); //v0=fromMem(); + expect(ops.vars).toEqual([2,1,2,3]); + + org.mem.splice(0, org.mem.length, ...[0,1,2,3]); + expect(ops.onFromMem(0x0b58ffff, 0, org)).toEqual(1); //v1=fromMem(); + expect(ops.vars).toEqual([2,1,2,3]); + }); + + it("Checking getting value by variable floating value", () => { + ops.vars.splice(0, ops.vars.length, ...[.1,3.2,.3,.4]); + org.mem.splice(0, org.mem.length, ...[1,2,3,4]); + expect(ops.onFromMem(0x0b1fffff, 0, org)).toEqual(1); //v0=fromMem(); + expect(ops.vars).toEqual([4,3.2,.3,.4]); + + ops.vars.splice(0, ops.vars.length, ...[.1,3.2,.3,.4]); + org.mem.splice(0, org.mem.length, ...[0,1,2,3]); + expect(ops.onFromMem(0x0b58ffff, 0, org)).toEqual(1); //v1=fromMem(); + expect(ops.vars).toEqual([.1,3,.3,.4]); + }); }); it("Checking onToMem() method", () => { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 1bb7144..90ffa7c 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -82,7 +82,7 @@ class Organisms extends BaseOrganisms { // // Clone percent is always 0.5 // - let energy = (((orgEnergy * 0.5) + 0.5) << 1) >>> 1; // analog of Math.round() + let energy = (orgEnergy * .5 + .5) << 0; // analog of Math.round() // // This is very special/rare case, when organisms cheating by creating // ancestors and put all energy into them at the same time resetting @@ -268,7 +268,7 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - const energy = (((org.energy * OConfig.orgStepEnergySpendPercent) + 0.5) << 1) >>> 1; + const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; (org.energy <= energy) && this.parent.fire(EVENTS.KILL_STEP_IN, org); org.energy -= energy; } From a3dfb165b2ddc01704c6de09062871cc427262a6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 17:06:37 +0200 Subject: [PATCH 190/291] fixed few more tests #83 --- client/src/manager/plugins/organisms/Config.js | 4 ++-- .../plugins/organisms/dos/OperatorsSpec.js | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index be5173c..050cdd2 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -128,11 +128,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 3000, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 2000, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 451d262..3f6b575 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -849,6 +849,23 @@ describe("client/src/organism/OperatorsDos", () => { expect(ops.onFromMem(0x0b58ffff, 0, org)).toEqual(1); //v1=fromMem(); expect(ops.vars).toEqual([.1,3,.3,.4]); }); + + it("Checking getting value by variable value with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.mem.splice(0, org.mem.length, ...[1,2,3,4]); + expect(ops1.onFromMem(0x0b0fffff, 0, org)).toEqual(1); //v1=fromMem(); + expect(ops1.vars).toEqual([1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + + org.mem.splice(0, org.mem.length, ...[0,7,2,3]); + expect(ops1.onFromMem(0x0b51ffff, 0, org)).toEqual(1); //v5=fromMem(); + expect(ops1.vars).toEqual([1,1,2,3,4,7,6,7,8,9,10,11,12,13,14,15]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); it("Checking onToMem() method", () => { From f21463e6806e51ea02b03220338b296d4e4c1d25 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 18:39:16 +0200 Subject: [PATCH 191/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 50 ++++++++++++++----- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 3f6b575..cb4f720 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -811,12 +811,12 @@ describe("client/src/organism/OperatorsDos", () => { describe('onFromMem() method', () => { let org; let ops; - const mbits = OConfig.orgMemBits; - OConfig.orgMemBits = 2; + let mbits; beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); - afterAll(() => OConfig.orgMemBits = mbits); + beforeAll(() => {mbits = OConfig.orgMemBits; OConfig.orgMemBits = 2}); + afterAll(() => OConfig.orgMemBits = mbits); it("Checking getting value by constant", () => { org.mem.splice(0, org.mem.length, ...[1,2,3,4]); @@ -868,20 +868,44 @@ describe("client/src/organism/OperatorsDos", () => { }); }); - it("Checking onToMem() method", () => { - let org = {mem: []}; - let ops = new OperatorsDos([], [0, 1, 2, 3], new Observer()); + describe('onToMem() method', () => { + let org; + let ops; + let mbits; - expect(ops.onToMem(0x0effffff, 0, org, 1)).toEqual(1); //'v3 = org.toMem(v3)'); - expect(org.mem[0]).toEqual(3); - expect(ops.onToMem(0x0e6fffff, 0, org, 1)).toEqual(1); //'v1 = org.toMem(v2)'); - expect(org.mem[1]).toEqual(2); - expect(ops.onToMem(0x0e1fffff, 0, org, 1)).toEqual(1); //'v0 = org.toMem(v1)'); - expect(org.mem[2]).toEqual(2); + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + beforeAll(() => {mbits = OConfig.orgMemBits; OConfig.orgMemBits = 2}); + afterAll(() => OConfig.orgMemBits = mbits); - ops.destroy(); + it("Checking setting value by constant", () => { + org.mem.splice(0, org.mem.length, ...[1,2,3,4]); + expect(ops.onToMem(0x0b17ffff, 0, org)).toEqual(1); //toMem(v0, 3); + expect(org.mem).toEqual([1,2,3,0]); + }); + + it("Checking setting value by variable value", () => { + org.mem.splice(0, org.mem.length, ...[0,2,3,4]); + expect(ops.onToMem(0x0b1fffff, 0, org)).toEqual(1); //toMem(v0, v0); + expect(org.mem).toEqual([1,2,3,4]); + }); + + it("Checking setting value by variable value with 4 bits per var", () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.mem.splice(0, org.mem.length, ...[0,2,3,4]); + expect(ops1.onToMem(0x0b1fffff, 0, org)).toEqual(1); //toMem(v0, v0); + expect(org.mem).toEqual([0,15,3,4]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); + + it("Checking onMyX() method", () => { let org = {x: 1, y:2}; let ops = new OperatorsDos([], [0, 7, 2, 3], new Observer()); From 66bc4204f4eefecc384477666a2c195cc6d6396d Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 18 Feb 2018 19:00:20 +0200 Subject: [PATCH 192/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 116 +++++++++++------- 1 file changed, 74 insertions(+), 42 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index cb4f720..44325b5 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -905,49 +905,81 @@ describe("client/src/organism/OperatorsDos", () => { }); + describe('onMyX() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); - it("Checking onMyX() method", () => { - let org = {x: 1, y:2}; - let ops = new OperatorsDos([], [0, 7, 2, 3], new Observer()); - - expect(ops.onMyX(0x0f1fffff, 0, org, 1)).toEqual(1); // v0=org.myX(); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyX(0x0f6fffff, 0, org, 1)).toEqual(1); // v1=org.myX(); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyX(0x0fffffff, 0, org, 1)).toEqual(1); // v3=org.myX(); - expect(ops.vars[0] === 1).toEqual(true); - expect(ops.vars[1] === 1).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 1).toEqual(true); - - ops.destroy(); + it("Checking simple values", () => { + org.x = 1; + expect(ops.onMyX(0x0c1fffff, 0, org)).toEqual(1); // v0=myX() + expect(ops.vars).toEqual([1,1,2,3]); + org.x = 3; + expect(ops.onMyX(0x0c6fffff, 0, org)).toEqual(1); // v1=myX() + expect(ops.vars).toEqual([1,3,2,3]); + org.x = 0; + expect(ops.onMyX(0x0cffffff, 0, org)).toEqual(1); // v3=myX() + expect(ops.vars).toEqual([1,3,2,0]); + }); + + it('Checking simple values with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.x = 3; + expect(ops1.onMyX(0x0c1fffff, 0, org)).toEqual(1); // v1=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + org.x = 3; + expect(ops1.onMyX(0x0c6fffff, 0, org)).toEqual(1); // v6=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,3,7,8,9,10,11,12,13,14,15]); + org.x = 0; + expect(ops1.onMyX(0x0cffffff, 0, org)).toEqual(1); // v15=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,3,7,8,9,10,11,12,13,14,0]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); - it("Checking onMyX() method", () => { - let org = {x: 1, y:2}; - let ops = new OperatorsDos([], [0, 7, 2, 3], new Observer()); - - expect(ops.onMyY(0x0f1fffff, 0, org, 1)).toEqual(1); // v0=org.myY(); - expect(ops.vars[0] === 2).toEqual(true); - expect(ops.vars[1] === 7).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyY(0x0f6fffff, 0, org, 1)).toEqual(1); // v1=org.myY(); - expect(ops.vars[0] === 2).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 3).toEqual(true); - expect(ops.onMyY(0x0fffffff, 0, org, 1)).toEqual(1); // v3=org.myY(); - expect(ops.vars[0] === 2).toEqual(true); - expect(ops.vars[1] === 2).toEqual(true); - expect(ops.vars[2] === 2).toEqual(true); - expect(ops.vars[3] === 2).toEqual(true); - - ops.destroy(); + + describe('onMyY() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it("Checking simple values", () => { + org.y = 1; + expect(ops.onMyY(0x0c1fffff, 0, org)).toEqual(1); // v0=myY() + expect(ops.vars).toEqual([1,1,2,3]); + org.y = 3; + expect(ops.onMyY(0x0c6fffff, 0, org)).toEqual(1); // v1=myY() + expect(ops.vars).toEqual([1,3,2,3]); + org.y = 0; + expect(ops.onMyY(0x0cffffff, 0, org)).toEqual(1); // v3=myY() + expect(ops.vars).toEqual([1,3,2,0]); + }); + + it('Checking simple values with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.y = 3; + expect(ops1.onMyY(0x0c1fffff, 0, org)).toEqual(1); // v1=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,6,7,8,9,10,11,12,13,14,15]); + org.y = 3; + expect(ops1.onMyY(0x0c6fffff, 0, org)).toEqual(1); // v6=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,3,7,8,9,10,11,12,13,14,15]); + org.y = 0; + expect(ops1.onMyY(0x0cffffff, 0, org)).toEqual(1); // v15=myX() + expect(ops1.vars).toEqual([0,3,2,3,4,5,3,7,8,9,10,11,12,13,14,0]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); }); \ No newline at end of file From a7f99252b2d86e49a122480948b637eb665ebcf5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 19 Feb 2018 09:26:07 +0200 Subject: [PATCH 193/291] fixed few more tests #83 --- client/src/manager/plugins/organisms/Organism.js | 12 ++++++++---- client/src/manager/plugins/organisms/Organisms.js | 12 ++++++------ .../manager/plugins/organisms/dos/OperatorsSpec.js | 1 - 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 14f9da0..9e032d4 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -252,10 +252,14 @@ class Organism extends Observer { _updateClone() { if ((this._energy > this._nextClone) && this.vm.size > 0) { - const ratio = this._energy / this._nextClone; - const clones = Math.floor(ratio); - if (this.fire(CLONE, this, clones) && this._alive) { - this._nextClone = this._energy + OConfig.orgCloneMinEnergy * (this.vm.size || 1) * ((1 - (ratio - clones)) || 1); + const minEnergy = OConfig.orgCloneMinEnergy * (this.vm.size || 1); + const clones = Math.ceil((this._energy - this._nextClone) / minEnergy); + const prob = (this._energy / this._nextClone) - 1.0; + const ret = {ret: false}; + + this.fire(CLONE, this, clones, prob, ret); + if (ret.ret && this._alive) { + this._nextClone = this._energy + minEnergy; } } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index afb8b02..70c51dc 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -267,13 +267,15 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - _onCloneOrg(org, amount) { + _onCloneOrg(org, amount, prob, ret) { const maxOrgs = OConfig.orgMaxOrgs; - const killOnClone = OConfig.orgKillOnClone; + const killOnClone = OConfig.orgKillOnClone || Math.random() < prob; + const orgsAvail = Math.min(killOnClone ? amount : maxOrgs - this.organisms.size, amount); - for (let i = 0; i < amount; i++) { + ret.ret = false; + for (let i = 0; i < orgsAvail; i++) { if (org.alive && (killOnClone || this.organisms.size < maxOrgs)) { - this._clone(org) + ret.ret = this._clone(org); } } @@ -282,8 +284,6 @@ class Organisms extends Configurable { if (killOnClone && orgAmount >= maxOrgs) { for (let i = maxOrgs; i < orgAmount; i++) {this.randOrg().destroy()} } - - return true; } _killInTour() { diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 44325b5..8666ef9 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -904,7 +904,6 @@ describe("client/src/organism/OperatorsDos", () => { }); }); - describe('onMyX() method', () => { let org; let ops; From 35b48c8fb02389c6a3d96619606d9c9bd5cbf44a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 19 Feb 2018 23:25:13 +0200 Subject: [PATCH 194/291] fixed organisms out of world issue added new killing on clone mechanism. only top energetic organisms have higher possibility to clone --- .../src/manager/plugins/organisms/Config.js | 8 +-- .../src/manager/plugins/organisms/Organism.js | 16 +----- .../manager/plugins/organisms/Organisms.js | 52 +++++++++---------- .../plugins/organisms/dos/Organisms.js | 7 --- client/src/view/World.js | 2 +- 5 files changed, 32 insertions(+), 53 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 050cdd2..4ef5c8d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -53,14 +53,14 @@ const Config = { * If amount of energy less then orgCloneMinEnergy * vm.size, then clone * is not possible */ - orgCloneMinEnergy: 1000, + orgCloneMinEnergy: 10000, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing * will be provided. Killing of organism will be done using random organism * selection from population */ - orgKillOnClone: true, + orgKillOnClone: false, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -128,11 +128,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 500, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 1000, + orgStartAmount: 500, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 9e032d4..2b455aa 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -80,7 +80,6 @@ class Organism extends Observer { this._x = x; this._y = y; this._iterations = -1; - this._nextClone = this._energy + OConfig.orgCloneMinEnergy; this._changes = 0; this._alive = alive; this._item = item; @@ -149,7 +148,6 @@ class Organism extends Observer { alive : this._alive, // 'item' will be added after insertion iterations : this._iterations, - nextClone : this._nextClone, fnId : this._fnId, vm : this.vm.serialize(), energy : this._energy, @@ -180,7 +178,6 @@ class Organism extends Observer { this._alive = json.alive; // 'item' will be added after insertion this._iterations = json.iterations; - this._nextClone = json.nextClone; this._fnId = json.fnId; this.vm.unserialize(json.vm); this._energy = json.energy; @@ -213,7 +210,6 @@ class Organism extends Observer { this.vm && this.vm.destroy(); this.vm = null; this._operatorCls = null; - this._nextClone = null; this._iterations = -1; super.destroy(); @@ -251,16 +247,8 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > this._nextClone) && this.vm.size > 0) { - const minEnergy = OConfig.orgCloneMinEnergy * (this.vm.size || 1); - const clones = Math.ceil((this._energy - this._nextClone) / minEnergy); - const prob = (this._energy / this._nextClone) - 1.0; - const ret = {ret: false}; - - this.fire(CLONE, this, clones, prob, ret); - if (ret.ret && this._alive) { - this._nextClone = this._energy + minEnergy; - } + if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0) { + this.fire(CLONE, this); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 70c51dc..8b9efc6 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -73,13 +73,6 @@ class Organisms extends Configurable { */ createEmptyOrg(...args) {} - /** - * Is called at the end of run() method - * @param {Organism} org Current organism - * @abstract - */ - onOrganism(org) {} - constructor(manager) { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; @@ -88,6 +81,8 @@ class Organisms extends Configurable { this.world = manager.world; this._mutator = new Mutator(manager, this); + this._maxEnergy = 0; + this._oldMaxEnergy = 0; this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -111,6 +106,20 @@ class Organisms extends Configurable { super.destroy(); } + /** + * Is called at the end of run() method + * @param {Organism} org Current organism + * @abstract + */ + onOrganism(org) { + if (org.energy > this._oldMaxEnergy) {this._oldMaxEnergy = org.energy} + + if (org === this.organisms.last.val) { + this._maxEnergy = this._oldMaxEnergy; + this._oldMaxEnergy = 0; + } + } + addOrgHandlers(org) { org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); @@ -175,13 +184,12 @@ class Organisms extends Configurable { * @param {Number} stamp Time stamp of current iteration */ _onIteration(counter, stamp) { - const onOrganism = this.onOrganism.bind(this); - let item = this.organisms.first; + let item = this.organisms.first; let org; while (org = item && item.val) { org.run(); - onOrganism(org); + this.onOrganism(org); item = item.next; } @@ -254,7 +262,7 @@ class Organisms extends Configurable { } } this.organisms.del(org.item); - this.world.setDot(org.x, org.y, 0); + this.world.setDot(org.x, org.y, org.energy > 0 ? org.energy : 0); this.onAfterKillOrg(org); this.parent.fire(EVENTS.KILL, org); //Console.info(org.id, ' die'); @@ -267,23 +275,13 @@ class Organisms extends Configurable { this._parent.fire(EVENTS.CODE_RUN, lines, org); } - _onCloneOrg(org, amount, prob, ret) { - const maxOrgs = OConfig.orgMaxOrgs; - const killOnClone = OConfig.orgKillOnClone || Math.random() < prob; - const orgsAvail = Math.min(killOnClone ? amount : maxOrgs - this.organisms.size, amount); - - ret.ret = false; - for (let i = 0; i < orgsAvail; i++) { - if (org.alive && (killOnClone || this.organisms.size < maxOrgs)) { - ret.ret = this._clone(org); - } - } - - //if (OConfig.orgKillOnClone && ret && orgAmount + 1 >= maxOrgs) {this._killInTour()} + _onCloneOrg(org) { + const maxOrgs = OConfig.orgMaxOrgs; const orgAmount = this.organisms.size; - if (killOnClone && orgAmount >= maxOrgs) { - for (let i = maxOrgs; i < orgAmount; i++) {this.randOrg().destroy()} - } + + //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} + if ((OConfig.orgKillOnClone || Math.random() <= org.energy / (this._maxEnergy * orgAmount)) && orgAmount >= maxOrgs) {this.randOrg().destroy()} + if (org.alive && this.organisms.size < maxOrgs) {this._clone(org)} } _killInTour() { diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 90ffa7c..144081f 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -105,7 +105,6 @@ class Organisms extends BaseOrganisms { org.on(EVENTS.EAT, this._onEat.bind(this)); org.on(EVENTS.STEP, this._onStep.bind(this)); org.on(EVENTS.CHECK_AT, this._onCheckAt.bind(this)); - org.on(OEVENTS.DESTROY, this._onOrgDestroy.bind(this)); } /** @@ -243,12 +242,6 @@ class Organisms extends BaseOrganisms { } } - _onOrgDestroy(org) { - if (org.energy > 0) { - this.parent.world.setDot(org.x, org.y, org.energy); - } - } - /** * Is called if organism step in from the server or other client (Manager/World). * If step in position is not free or maximum organisms are in the world, then diff --git a/client/src/view/World.js b/client/src/view/World.js index 76010c7..ee77ca2 100644 --- a/client/src/view/World.js +++ b/client/src/view/World.js @@ -103,7 +103,7 @@ class World extends Observer { ]; for (let i = 0, j = 0; i < 8; i++) { - if (this.getDot(positions[j], positions[j + 1]) === 0) { + if (this.getDot(positions[j], positions[j + 1]) === 0 && x >= 0 && x < this._width && y >= 0 && y < this._height) { return {x: positions[j], y: positions[j + 1]}; } j += 2; From 06e64ca74c4a5e56c413f28d7ee3d853334f68c8 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 01:23:46 +0200 Subject: [PATCH 195/291] added random energy creation --- client/src/manager/plugins/Energy.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 7d9832a..43ae3e0 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -8,9 +8,13 @@ const Config = require('./../../share/Config').Config; const Console = require('./../../share/Console'); const EVENTS = require('./../../share/Events').EVENTS; +const POSID = Helper.posId; + class Energy { constructor(manager) { this._manager = manager; + this._lastX = -1; + this._lastY = -1; this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onIteration', this._onIterationCb); @@ -23,6 +27,7 @@ class Energy { } _onIteration(counter) { + this._updateAliveEnergy(); if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); @@ -62,6 +67,23 @@ class Energy { } this._manager.fire(EVENTS.UPDATE_ENERGY); } + + _updateAliveEnergy() { + const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); + const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); + const world = this._manager.world; + const positions = this._manager.positions; + const dot = world.getDot(x, y); + + if (typeof(positions[POSID(x, y)]) === 'undefined') { + dot === 0 && world.setDot(x, y, Config.worldEnergyInDot); + this._lastX = x + Helper.rand(3) - 1; + this._lastY = y + Helper.rand(3) - 1; + if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, dot)} + return; + } + this._lastX = this._lastY = -1; + } } module.exports = Energy; \ No newline at end of file From e5946666c6095f17565572a0a212442501e02c3b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 01:34:18 +0200 Subject: [PATCH 196/291] fixed an issue of out of world energy --- client/src/manager/plugins/Energy.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 43ae3e0..387cae9 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -75,6 +75,9 @@ class Energy { const positions = this._manager.positions; const dot = world.getDot(x, y); + if (x < 0 || x >= Config.worldWidth) {this._lastX = -1; return} + if (y < 0 || y >= Config.worldHeight) {this._lastY = -1; return} + if (typeof(positions[POSID(x, y)]) === 'undefined') { dot === 0 && world.setDot(x, y, Config.worldEnergyInDot); this._lastX = x + Helper.rand(3) - 1; From 174fd6bb15b84ce1a1e63d3e7971b97df16ef8a7 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 14:16:15 +0200 Subject: [PATCH 197/291] added orgCloneGrabEnergyPercent config from now amount of energy grabbed from organism for every operator depends on organism size --- .../src/manager/plugins/organisms/Config.js | 8 ++++++-- .../src/manager/plugins/organisms/Organism.js | 11 +++------- .../manager/plugins/organisms/Organisms.js | 20 ++++++++++++------- client/src/vm/VM.js | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4ef5c8d..e0753b7 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -54,6 +54,10 @@ const Config = { * is not possible */ orgCloneMinEnergy: 10000, + /** + * {Number} Percent of energy, which will be grabbed from organism after clone + */ + orgCloneGrabEnergyPercent: .8, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing @@ -128,11 +132,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 500, + orgMaxOrgs: 2000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 500, + orgStartAmount: 2000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 2b455aa..b6d4e75 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -119,15 +119,10 @@ class Organism extends Observer { run() { this._iterations++; if (this.onBeforeRun() === false) {return true} - // - // IMPORTANT: cloning must be before onRun() to prevent - // IMPORTANT: app hang (very long loops), when organism - // IMPORTANT: eats itself) - // - this._alive && this._updateClone(); const lines = this._alive ? this.onRun() : 0; if (this._alive) { - this._updateEnergy(); + this._updateClone(); + this._alive && this._updateEnergy(); this._alive && this.fire(ITERATION, lines, this); this._alive && this._updateAge(); } @@ -247,7 +242,7 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0) { + if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0 && this._alive) { this.fire(CLONE, this); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 8b9efc6..198f3f8 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -109,10 +109,10 @@ class Organisms extends Configurable { /** * Is called at the end of run() method * @param {Organism} org Current organism - * @abstract */ onOrganism(org) { - if (org.energy > this._oldMaxEnergy) {this._oldMaxEnergy = org.energy} + const energy = org.energy / org.vm.size; + if (energy > this._oldMaxEnergy) {this._oldMaxEnergy = energy} if (org === this.organisms.last.val) { this._maxEnergy = this._oldMaxEnergy; @@ -189,7 +189,7 @@ class Organisms extends Configurable { while (org = item && item.val) { org.run(); - this.onOrganism(org); + org.alive && this.onOrganism(org); item = item.next; } @@ -276,12 +276,18 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - const maxOrgs = OConfig.orgMaxOrgs; - const orgAmount = this.organisms.size; + //const maxOrgs = OConfig.orgMaxOrgs; + //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} - if ((OConfig.orgKillOnClone || Math.random() <= org.energy / (this._maxEnergy * orgAmount)) && orgAmount >= maxOrgs) {this.randOrg().destroy()} - if (org.alive && this.organisms.size < maxOrgs) {this._clone(org)} + //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this.randOrg().destroy()} + if (this.organisms.size < OConfig.orgMaxOrgs && this._clone(org)) { + // + // Decrease amount of energy after clone from parent and child + // + org.energy *= (1 - OConfig.orgCloneGrabEnergyPercent); + this.organisms.last.val.energy *= (1 - OConfig.orgCloneGrabEnergyPercent); + } } _killInTour() { diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 56d1b87..e7fa6c5 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -101,7 +101,7 @@ class VM extends Observer { while (len > 0 && org.energy > 0) { operator = code[line] >>> OFFS; line = ops[operator](code[line], line, org, lines); - org.energy -= this._weights[operator]; + org.energy -= (this._weights[operator] * lines); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 2a05555fdae02134ce223f7bb0e71a01956056e0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 16:53:47 +0200 Subject: [PATCH 198/291] added killed, age and orgas values to the header of the world --- client/src/manager/plugins/organisms/Config.js | 6 +++--- client/src/manager/plugins/status/charts/Charts.js | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index e0753b7..5ba2cb6 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -57,7 +57,7 @@ const Config = { /** * {Number} Percent of energy, which will be grabbed from organism after clone */ - orgCloneGrabEnergyPercent: .8, + orgCloneGrabEnergyPercent: .5, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing @@ -117,7 +117,7 @@ const Config = { * {Number} Percent of energy, which will be minused from organism after * stepping from one instance to another. */ - orgStepEnergySpendPercent: 0.1, + orgStepEnergySpendPercent: .0, /** * {Number} Percent from orgMaxOrgs config, which is used for crossing borders * between clients/Managers. Entire amount of organisms within one client = @@ -126,7 +126,7 @@ const Config = { * the border (every organism will be returned back, but there will not be free * space at that time). In this situation crossing organism just die during crossing. */ - orgStepOverflowPercent: 0.1, + orgStepOverflowPercent: 0.2, /** * {Number} Maximum amount of organisms in a world. If some organism will * try to clone itself, when entire amount of organisms are equal diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 2d43439..b2691ad 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -144,8 +144,11 @@ class Charts extends Status { const ips = `ips:${status.ips}`; const enrg = `enrg:${status.eenergy}`; const code = `cod:${status.code}`; + const age = `age:${status.age}`; + const kill = `kil:${status.kill}`; + const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${enrg} ${code}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${enrg} ${code} ${age} ${kill} ${orgs}`; } _to12h(time) { From 04208ecf33495725bd5405e3a695e3fa071ae3cd Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 16:59:16 +0200 Subject: [PATCH 199/291] added killed, age and orgas values to the header of the world added clever energy config: worldCleverEnergy --- client/src/manager/Manager.js | 2 +- client/src/manager/plugins/Energy.js | 2 +- client/src/share/Config.js | 13 +++++++------ client/src/view/Canvas.js | 8 ++++---- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index bc6c888..c39461a 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -67,7 +67,7 @@ class Manager extends Observer { this._codeRuns = 0; this._world = new World(Config.worldWidth, Config.worldHeight); - this._canvas = hasView && new Canvas(Config.worldWidth, Config.worldHeight, Config.worldNoScrolls) || null; + this._canvas = hasView && new Canvas(Config.worldWidth, Config.worldHeight) || null; this._visualized = true; this._running = false; this._active = false; diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 387cae9..5971458 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -27,7 +27,7 @@ class Energy { } _onIteration(counter) { - this._updateAliveEnergy(); + Config.worldCleverEnergy && this._updateAliveEnergy(); if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 5d9988e..3efc8a4 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -76,6 +76,11 @@ ClientConfig.init({ * config for details. */ worldEnergyInDot: 0x00ddff, + /** + * {Boolean} Analog of trees. This type of energy is growing all the time + * using random walk algorithm. + */ + worldCleverEnergy: true, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less @@ -83,17 +88,13 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.1, + worldEnergyCheckPercent: 0.05, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if * you want to disable it */ - worldEnergyCheckPeriod: 1000, - /** - * {Boolean} Turns on/off scroll bars in a 2D canvas - */ - worldNoScrolls: true, + worldEnergyCheckPeriod: 5000, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/view/Canvas.js b/client/src/view/Canvas.js index 43b7a50..20b405a 100644 --- a/client/src/view/Canvas.js +++ b/client/src/view/Canvas.js @@ -8,7 +8,7 @@ const Helper = require('./../../../common/src/Helper'); const Config = require('./../share/Config').Config; class Canvas { - constructor(width, height, noScrolls = false) { + constructor(width, height) { const id = 'world'; const doc = document; @@ -26,7 +26,7 @@ class Canvas { this._panZoom = null; this._fullEl = this._createFullScreen(); - this._prepareDom(noScrolls); + this._prepareDom(); this._initPanZoomLib(); this.clear(); window.requestAnimationFrame(this._animate); @@ -118,7 +118,7 @@ class Canvas { } } - _prepareDom(noScrolls) { + _prepareDom() { const bodyEl = document.body; const htmlEl = document.querySelector('html'); @@ -139,7 +139,7 @@ class Canvas { // // This style hides scroll bars on full screen 2d canvas // - if (noScrolls) {document.querySelector('html').style.overflow = 'hidden'} + document.querySelector('html').style.overflow = 'hidden'; } /** From 0d833a5f6340ad9a88b5562ed7737a38ab0cab02 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 18:02:03 +0200 Subject: [PATCH 200/291] fixed an issue with no data for hidden charts --- client/src/manager/plugins/Energy.js | 4 +- .../manager/plugins/status/charts/Chart.js | 12 +++--- .../manager/plugins/status/charts/Charts.js | 2 +- .../manager/plugins/status/charts/Config.js | 38 +++++++++---------- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 5971458..d523db1 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -27,7 +27,7 @@ class Energy { } _onIteration(counter) { - Config.worldCleverEnergy && this._updateAliveEnergy(); + Config.worldCleverEnergy && this._updateCleverEnergy(); if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); @@ -68,7 +68,7 @@ class Energy { this._manager.fire(EVENTS.UPDATE_ENERGY); } - _updateAliveEnergy() { + _updateCleverEnergy() { const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); const world = this._manager.world; diff --git a/client/src/manager/plugins/status/charts/Chart.js b/client/src/manager/plugins/status/charts/Chart.js index 261a582..6cdc962 100644 --- a/client/src/manager/plugins/status/charts/Chart.js +++ b/client/src/manager/plugins/status/charts/Chart.js @@ -1,7 +1,7 @@ /** * Draws one line chart using Google charts library. The purpose of * this class is to show dynamics of changing for some property. For - * example: energy, iq or code size. update() method should obtain + * example: energy, age or code size. update() method should obtain * new portion of property data to draw on chart. Works only in browser. * Requires internet connection for google charts dynamic load. * @@ -51,7 +51,7 @@ class Chart { set transparent(t) {this._el && (this._el.style.opacity = t)} set pos(p) {this._updatePos(p)} - set active(a) {this._cfg.active !== a && this._updateActive(a)} + set active(a) {this._updateActive(a)} reset() { if (!this._ready) {return false} @@ -73,7 +73,7 @@ class Chart { const googleLib = window.google; const setReadyCb = () => { window.google.charts.load('current', {'packages': ['corechart']}); - window.google.charts.setOnLoadCallback(() => this._cfg.active && cb()); + window.google.charts.setOnLoadCallback(() => cb()); }; // // Google charts library has already loaded @@ -96,15 +96,17 @@ class Chart { } _onReady() { + this._ready = true; + !this._data && (this._data = this._createDataTable()); + if (!this._cfg.active || this._el) {return} + document.body.appendChild(this._el = Helper.setStyles('DIV', { position: 'absolute', opacity : this._cfg.transparent })); this._updatePos(this._cfg.pos); - this._ready = true; this._chart = new window.google.visualization.LineChart(this._el); - !this._data && (this._data = this._createDataTable()); } /** diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index b2691ad..824506d 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -290,8 +290,8 @@ class Charts extends Status { _setProperty(chart, prop, val) { if (typeof(this._charts[chart]) === 'undefined') {return} - this._charts[chart][prop] = val; _has(this.cfg, `charts.${chart}.${prop}`) && (this.cfg.charts[chart][prop] = val); + this._charts[chart][prop] = val; } } diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index c74d21e..65a3a96 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -21,25 +21,25 @@ const Config = { * {Object} Available chart types */ charts: { - lps : {pos: 'downleft', active: false, transparent: 0.8}, - killout : {pos: 'topright', active: false, transparent: 0.8}, - energy : {pos: 'downright', active: false, transparent: 0.8}, - orgs : {pos: '0-0|16', active: true, transparent: 0.8}, - penergy : {pos: '0-1|16', active: true, transparent: 0.8}, - eenergy : {pos: '0-2|16', active: true, transparent: 0.8}, - fit : {pos: '0-3|16', active: true, transparent: 0.8}, - age : {pos: '1-0|16', active: true, transparent: 0.8}, - code : {pos: '1-1|16', active: true, transparent: 0.8}, - kill : {pos: '1-2|16', active: true, transparent: 0.8}, - killtour : {pos: '1-3|16', active: true, transparent: 0.8}, - killenergy: {pos: '2-0|16', active: true, transparent: 0.8}, - killage : {pos: '2-1|16', active: true, transparent: 0.8}, - killeat : {pos: '2-2|16', active: true, transparent: 0.8}, - killover : {pos: '2-3|16', active: true, transparent: 0.8}, - changes : {pos: '3-0|16', active: true, transparent: 0.8}, - killin : {pos: '3-1|16', active: true, transparent: 0.8}, - killclone : {pos: '3-2|16', active: true, transparent: 0.8}, - ips : {pos: '3-3|16', active: true, transparent: 0.8} + lps : {pos: 'downleft', active: false, transparent: 0.8}, + killout : {pos: 'topright', active: false, transparent: 0.8}, + energy : {pos: 'downright', active: false, transparent: 0.8}, + orgs : {pos: '0-0|16', active: false, transparent: 0.8}, + penergy : {pos: '0-1|16', active: false, transparent: 0.8}, + eenergy : {pos: '0-2|16', active: false, transparent: 0.8}, + fit : {pos: '0-3|16', active: false, transparent: 0.8}, + age : {pos: '1-0|16', active: false, transparent: 0.8}, + code : {pos: '1-1|16', active: false, transparent: 0.8}, + kill : {pos: '1-2|16', active: false, transparent: 0.8}, + killtour : {pos: '1-3|16', active: false, transparent: 0.8}, + killenergy: {pos: '2-0|16', active: false, transparent: 0.8}, + killage : {pos: '2-1|16', active: false, transparent: 0.8}, + killeat : {pos: '2-2|16', active: false, transparent: 0.8}, + killover : {pos: '2-3|16', active: false, transparent: 0.8}, + changes : {pos: '3-0|16', active: false, transparent: 0.8}, + killin : {pos: '3-1|16', active: false, transparent: 0.8}, + killclone : {pos: '3-2|16', active: false, transparent: 0.8}, + ips : {pos: '3-3|16', active: false, transparent: 0.8} } }; From 0212f74bf688d5dce5462ea317d55e5599252f88 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 21:33:56 +0200 Subject: [PATCH 201/291] fixed more tests #83 --- .../src/manager/plugins/organisms/Config.js | 4 +- .../plugins/organisms/dos/OrganismSpec.js | 61 ++++++++++--------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5ba2cb6..c54e76f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -144,8 +144,8 @@ const Config = { */ orgStartEnergy: 10000000, /** - * {Number} Begin color of "empty". It's just an index of color. Starts from - * 0 and till Number.MAX_VALUE + * {Number} Begin color of "empty" organism. It's just an index of color. + * Starts from0 and till Number.MAX_VALUE */ orgStartColor: 50, /** diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 325a4c4..0fc2ad4 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -2,58 +2,61 @@ // This spec covers two classes "Organism" and "OrganismDos" // describe("client/src/organism/OrganismDos", () => { - const eq = require('lodash/isEqual'); + const _fill = require('lodash/fill'); const OrganismDos = require('./Organism'); const OConfig = require('./../../../../manager/plugins/organisms/Config'); - const api = require('./../../../../share/Config').api; it("Checking organism creation", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos('0', 1, 2, true, null); - expect(org.id).toEqual(0); + expect(org.id).toEqual('0'); expect(org.x).toEqual(1); expect(org.y).toEqual(2); expect(org.item).toEqual(null); expect(org.alive).toEqual(true); - expect(eq(org.mutationProbs, OConfig.orgMutationProbs)).toEqual(true); + expect(org.mutationProbs).toEqual(OConfig.orgMutationProbs); + expect(org.mutationProbs !== OConfig.orgMutationProbs).toEqual(true); expect(org.mutationPeriod === OConfig.orgRainMutationPeriod).toEqual(true); expect(org.mutationPercent === OConfig.orgRainMutationPercent).toEqual(true); - expect(org.cloneMutationPercent === OConfig.orgCloneMutationPercent).toEqual(true); - expect(org.changes === 1).toEqual(true); - expect(org.energy === OConfig.orgStartEnergy).toEqual(true); - expect(org.color === OConfig.orgStartColor).toEqual(true); - expect(org.mem.length === 0).toEqual(true); - expect(org.iterations === 0).toEqual(true); + expect(org.mem.length).toBe(Math.pow(2, OConfig.orgMemBits)); + expect(org.mem).toEqual(_fill(new Array(Math.pow(2, OConfig.orgMemBits)), 0)); + expect(org.changes).toBe(0); + expect(org.energy).toBe(OConfig.orgStartEnergy); + expect(org.iterations).toBe(-1); org.destroy(); }); it("Checking organism creation from parent", () => { - const parent = new OrganismDos(1, 3, 4, true, null, () => {}); + const memSize = OConfig.orgMemBits; + const parent = new OrganismDos('1', 3, 4, true, null); + + OConfig.orgMemBits = 2; parent.vm.insertLine(); parent.energy = 123; parent.changes = 0xaabbcc; - parent._mutationProbs = [5,8,1,10,1,2,32,7]; - parent.cloneMutationPercent = 0.1; + parent.mutationProbs.splice(0, parent.mutationProbs.length, ...[5,8,1,10,1,2,32,7]); parent.mutationPeriod = 145; parent.mutationPercent = 0.2; - parent._mem = [1,2,4,3]; - - let org = new OrganismDos(0, 1, 2, true, null, () => {}, parent); - - expect(org.vm.code[0] === parent.vm.code[0]).toEqual(true); - expect(org.vm.size === parent.vm.size).toEqual(true); - expect(org.energy === parent.energy).toEqual(true); - expect(org.color === parent.color).toEqual(true); - expect(eq(org.mutationProbs, parent.mutationProbs)).toEqual(true); - expect(org.cloneMutationPercent === parent.cloneMutationPercent).toEqual(true); - expect(org.mutationPeriod === parent.mutationPeriod).toEqual(true); - expect(org.mutationPercent === parent.mutationPercent).toEqual(true); - expect(eq(org.mem, parent.mem)).toEqual(true); - expect(org.changes === 1).toEqual(true); - expect(org.iterations === 0).toEqual(true); + parent.mem.splice(0, parent.mem.length, ...[1,2,4,3]); + + let org = new OrganismDos('0', 1, 2, true, null, parent); + + expect(org.vm.code).toEqual(parent.vm.code); + expect(org.vm.size).toEqual(parent.vm.size); + expect(org.energy).toEqual(parent.energy); + expect(org.color).toEqual(parent.color); + expect(org.mutationProbs).toEqual(parent.mutationProbs); + expect(org.mutationPeriod).toEqual(parent.mutationPeriod); + expect(org.mutationPercent).toEqual(parent.mutationPercent); + expect(org.mem).toEqual(parent.mem); + expect(org.changes).toEqual(0); + expect(org.iterations).toEqual(-1); + expect(org.alive).toEqual(true); + expect(org.item).toEqual(null); org.destroy(); + OConfig.orgMemBits = memSize; }); it("Checking organism coordinates", () => { From 72ef9d83dbd21f31e0ead7329fd5895744db9430 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 20 Feb 2018 21:55:21 +0200 Subject: [PATCH 202/291] removed storing energy after death, because it's created a problem of new energy generation during moving between worlds/clients --- .../manager/plugins/organisms/Organisms.js | 2 +- .../plugins/organisms/dos/OrganismSpec.js | 120 ++++++++---------- 2 files changed, 54 insertions(+), 68 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 198f3f8..61767e5 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -262,7 +262,7 @@ class Organisms extends Configurable { } } this.organisms.del(org.item); - this.world.setDot(org.x, org.y, org.energy > 0 ? org.energy : 0); + this.world.setDot(org.x, org.y, 0); this.onAfterKillOrg(org); this.parent.fire(EVENTS.KILL, org); //Console.info(org.id, ' die'); diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 0fc2ad4..08d12f7 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -6,77 +6,63 @@ describe("client/src/organism/OrganismDos", () => { const OrganismDos = require('./Organism'); const OConfig = require('./../../../../manager/plugins/organisms/Config'); - it("Checking organism creation", () => { - let org = new OrganismDos('0', 1, 2, true, null); - - expect(org.id).toEqual('0'); - expect(org.x).toEqual(1); - expect(org.y).toEqual(2); - expect(org.item).toEqual(null); - expect(org.alive).toEqual(true); - expect(org.mutationProbs).toEqual(OConfig.orgMutationProbs); - expect(org.mutationProbs !== OConfig.orgMutationProbs).toEqual(true); - expect(org.mutationPeriod === OConfig.orgRainMutationPeriod).toEqual(true); - expect(org.mutationPercent === OConfig.orgRainMutationPercent).toEqual(true); - expect(org.mem.length).toBe(Math.pow(2, OConfig.orgMemBits)); - expect(org.mem).toEqual(_fill(new Array(Math.pow(2, OConfig.orgMemBits)), 0)); - expect(org.changes).toBe(0); - expect(org.energy).toBe(OConfig.orgStartEnergy); - expect(org.iterations).toBe(-1); - - org.destroy(); - }); - - it("Checking organism creation from parent", () => { - const memSize = OConfig.orgMemBits; - const parent = new OrganismDos('1', 3, 4, true, null); - - OConfig.orgMemBits = 2; - parent.vm.insertLine(); - parent.energy = 123; - parent.changes = 0xaabbcc; - parent.mutationProbs.splice(0, parent.mutationProbs.length, ...[5,8,1,10,1,2,32,7]); - parent.mutationPeriod = 145; - parent.mutationPercent = 0.2; - parent.mem.splice(0, parent.mem.length, ...[1,2,4,3]); - - let org = new OrganismDos('0', 1, 2, true, null, parent); - - expect(org.vm.code).toEqual(parent.vm.code); - expect(org.vm.size).toEqual(parent.vm.size); - expect(org.energy).toEqual(parent.energy); - expect(org.color).toEqual(parent.color); - expect(org.mutationProbs).toEqual(parent.mutationProbs); - expect(org.mutationPeriod).toEqual(parent.mutationPeriod); - expect(org.mutationPercent).toEqual(parent.mutationPercent); - expect(org.mem).toEqual(parent.mem); - expect(org.changes).toEqual(0); - expect(org.iterations).toEqual(-1); - expect(org.alive).toEqual(true); - expect(org.item).toEqual(null); - - org.destroy(); - OConfig.orgMemBits = memSize; - }); - - it("Checking organism coordinates", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); - - org.x = 4; - org.y = 5; - expect(org.x === 4 && org.y === 5).toEqual(true); - org.x = 0; - org.y = 0; - expect(org.x === 0 && org.y === 0).toEqual(true); - org.x = -1; - org.y = -2; - expect(org.x === -1 && org.y === -2).toEqual(true); + describe('Organism creation', () => { + it("Checking organism creation", () => { + let org = new OrganismDos('0', 1, 2, true, null); + + expect(org.id).toEqual('0'); + expect(org.x).toEqual(1); + expect(org.y).toEqual(2); + expect(org.item).toEqual(null); + expect(org.alive).toEqual(true); + expect(org.mutationProbs).toEqual(OConfig.orgMutationProbs); + expect(org.mutationProbs !== OConfig.orgMutationProbs).toEqual(true); + expect(org.mutationPeriod === OConfig.orgRainMutationPeriod).toEqual(true); + expect(org.mutationPercent === OConfig.orgRainMutationPercent).toEqual(true); + expect(org.mem.length).toBe(Math.pow(2, OConfig.orgMemBits)); + expect(org.mem).toEqual(_fill(new Array(Math.pow(2, OConfig.orgMemBits)), 0)); + expect(org.changes).toBe(0); + expect(org.energy).toBe(OConfig.orgStartEnergy); + expect(org.iterations).toBe(-1); + + org.destroy(); + }); + + it("Checking organism creation from parent", () => { + const memSize = OConfig.orgMemBits; + const parent = new OrganismDos('1', 3, 4, true, null); + + OConfig.orgMemBits = 2; + parent.vm.insertLine(); + parent.energy = 123; + parent.changes = 0xaabbcc; + parent.mutationProbs.splice(0, parent.mutationProbs.length, ...[5,8,1,10,1,2,32,7]); + parent.mutationPeriod = 145; + parent.mutationPercent = 0.2; + parent.mem.splice(0, parent.mem.length, ...[1,2,4,3]); + + let org = new OrganismDos('0', 1, 2, true, null, parent); + + expect(org.vm.code).toEqual(parent.vm.code); + expect(org.vm.size).toEqual(parent.vm.size); + expect(org.energy).toEqual(parent.energy); + expect(org.color).toEqual(parent.color); + expect(org.mutationProbs).toEqual(parent.mutationProbs); + expect(org.mutationPeriod).toEqual(parent.mutationPeriod); + expect(org.mutationPercent).toEqual(parent.mutationPercent); + expect(org.mem).toEqual(parent.mem); + expect(org.changes).toEqual(0); + expect(org.iterations).toEqual(-1); + expect(org.alive).toEqual(true); + expect(org.item).toEqual(null); - org.destroy(); + org.destroy(); + OConfig.orgMemBits = memSize; + }); }); it("Checking if organism if alive", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos('0', 1, 2, true, null); const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; const speriod = OConfig.orgEnergySpendPeriod; From 276468f39717176cbb2bf09cbbe012e7af7f04ce Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 00:45:31 +0200 Subject: [PATCH 203/291] amount of possible colors increased to 40000 --- client/src/manager/plugins/Energy.js | 30 +++++++++---------- .../src/manager/plugins/organisms/Organism.js | 8 ++--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index d523db1..990772a 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -3,18 +3,20 @@ * * @author flatline */ -const Helper = require('./../../../../common/src/Helper'); -const Config = require('./../../share/Config').Config; -const Console = require('./../../share/Console'); -const EVENTS = require('./../../share/Events').EVENTS; +const Helper = require('./../../../../common/src/Helper'); +const Config = require('./../../share/Config').Config; +const Organism = require('./../../manager/plugins/organisms/Organism').Organism; +const Console = require('./../../share/Console'); +const EVENTS = require('./../../share/Events').EVENTS; -const POSID = Helper.posId; +const MAX_INDEX = 40000; // depends on Organism.getColor.frequency constant class Energy { constructor(manager) { this._manager = manager; this._lastX = -1; this._lastY = -1; + this._energy = MAX_INDEX; this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onIteration', this._onIterationCb); @@ -72,20 +74,16 @@ class Energy { const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); const world = this._manager.world; - const positions = this._manager.positions; - const dot = world.getDot(x, y); - if (x < 0 || x >= Config.worldWidth) {this._lastX = -1; return} - if (y < 0 || y >= Config.worldHeight) {this._lastY = -1; return} - - if (typeof(positions[POSID(x, y)]) === 'undefined') { - dot === 0 && world.setDot(x, y, Config.worldEnergyInDot); - this._lastX = x + Helper.rand(3) - 1; - this._lastY = y + Helper.rand(3) - 1; - if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, dot)} + if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._energy < 0) { + this._lastX = this._lastY = -1; + this._energy = MAX_INDEX; return; } - this._lastX = this._lastY = -1; + + this._lastX = x + Helper.rand(3) - 1; + this._lastY = y + Helper.rand(3) - 1; + if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._energy))} } } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index b6d4e75..bdf7059 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -32,8 +32,8 @@ class Organism extends Observer { * @param {Number} index Color index. Starts from 0 till Number.MAX_VALUE * @returns {Number} RGB value */ - static _getColor(index) { - const frequency = 0.01; + static getColor(index) { + const frequency = 0.0001; const r = Math.sin(frequency * index ) * 127 + 128; const g = Math.sin(frequency * index + 2) * 127 + 128; @@ -215,7 +215,7 @@ class Organism extends Observer { this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; this._colorIndex = OConfig.orgStartColor * Num.MAX_BITS; - this._color = Organism._getColor(this._colorIndex); + this._color = Organism.getColor(this._colorIndex); this._mutationProbs = OConfig.orgMutationProbs.slice(); this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; @@ -238,7 +238,7 @@ class Organism extends Observer { _updateColor(changes) { this._colorIndex += (changes - this._changes); - this._color = Organism._getColor((this._colorIndex / Num.MAX_BITS + .5) << 0); + this._color = Organism.getColor((this._colorIndex / Num.MAX_BITS + .5) << 0); } _updateClone() { From d51ed8a5ac00a919a7e0b7737f20e4a9311b58c0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 10:25:16 +0200 Subject: [PATCH 204/291] added config worldCleverEnergyPercent --- client/src/manager/plugins/Energy.js | 20 +++++++++---------- .../src/manager/plugins/organisms/Organism.js | 7 +++++++ client/src/share/Config.js | 5 +++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 990772a..e4caac1 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -9,14 +9,13 @@ const Organism = require('./../../manager/plugins/organisms/Organism').Organism; const Console = require('./../../share/Console'); const EVENTS = require('./../../share/Events').EVENTS; -const MAX_INDEX = 40000; // depends on Organism.getColor.frequency constant - class Energy { constructor(manager) { this._manager = manager; this._lastX = -1; this._lastY = -1; - this._energy = MAX_INDEX; + this._colorIndex = Helper.rand(Organism.getMaxColors()); + this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyPercent; this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onIteration', this._onIterationCb); @@ -71,19 +70,20 @@ class Energy { } _updateCleverEnergy() { - const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); - const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); - const world = this._manager.world; + const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); + const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); - if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._energy < 0) { - this._lastX = this._lastY = -1; - this._energy = MAX_INDEX; + if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._amount < 0) { + this._lastX = this._lastY = -1; + this._colorIndex = Helper.rand(Organism.getMaxColors()); + this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyPercent; return; } + const world = this._manager.world; this._lastX = x + Helper.rand(3) - 1; this._lastY = y + Helper.rand(3) - 1; - if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._energy))} + if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex))} } } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index bdf7059..d996ebe 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -26,6 +26,8 @@ const ORG_EVENTS = { ITERATION }; +const MAX_COLORS = 40000; + class Organism extends Observer { /** * Returns color by index. Index may be increased without limit @@ -33,6 +35,9 @@ class Organism extends Observer { * @returns {Number} RGB value */ static getColor(index) { + // + // Maximum possible colors for this value is MAX_COLORS + // const frequency = 0.0001; const r = Math.sin(frequency * index ) * 127 + 128; @@ -42,6 +47,8 @@ class Organism extends Observer { return r << 16 | g << 8 | b; } + static getMaxColors() {return MAX_COLORS} + /** * Is called before every run. Should return true, if everything * is okay and we don't need to interrupt running. If true, then diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 3efc8a4..484cf56 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -81,6 +81,11 @@ ClientConfig.init({ * using random walk algorithm. */ worldCleverEnergy: true, + /** + * {Number} size of one clever energy block (percent from world size). Calculates + * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyPercent + */ + worldCleverEnergyPercent: 0.01, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less From a993aa4e58c45612b26863686111866d591ebb09 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 10:40:56 +0200 Subject: [PATCH 205/291] changed default config of clever energy block size --- client/src/share/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 484cf56..868185f 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -85,7 +85,7 @@ ClientConfig.init({ * {Number} size of one clever energy block (percent from world size). Calculates * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyPercent */ - worldCleverEnergyPercent: 0.01, + worldCleverEnergyPercent: 0.005, /** * {Number} Minimum percent of energy in current world. Under percent i mean * percent from entire world area (100%). If the energy will be less From 1ccd13a2df009a65ec2a4426ff2928054fc11ac1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 12:25:19 +0200 Subject: [PATCH 206/291] changed base logic of energy consumption: from now as more energy organism has as more energy he spends and as big code he has as more energy he spends added clever energy seasons: after some configured peak new energy will not be added until configured minimum of energy will be reached removed grabbing energy during cloning --- client/src/manager/plugins/Energy.js | 37 ++++++++++++------- .../src/manager/plugins/organisms/Config.js | 10 ++--- .../manager/plugins/organisms/Organisms.js | 8 +--- client/src/share/Config.js | 37 +++++++++++++------ client/src/vm/VM.js | 7 +++- 5 files changed, 59 insertions(+), 40 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index e4caac1..c8907c6 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -15,7 +15,8 @@ class Energy { this._lastX = -1; this._lastY = -1; this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyPercent; + this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyBlockPercent; + this._cleverActive = true; this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onIteration', this._onIterationCb); @@ -28,24 +29,19 @@ class Energy { } _onIteration(counter) { - Config.worldCleverEnergy && this._updateCleverEnergy(); + Config.worldCleverEnergy && this._cleverActive && this._updateCleverEnergy(); + if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); return; } - let energy = 0; - const world = this._manager.world; - const width = Config.worldWidth; - const height = Config.worldHeight; - for (let x = 0; x < width; x++) { - for (let y = 0; y < height; y++) { - if (world.getDot(x, y) > 0) {energy++} - } - } + const energyPercent = this._getEnergyPercent(); + if (energyPercent <= Config.worldCleverEnergyMinPercent) {this._cleverActive = true} + else if (energyPercent >= Config.worldCleverEnergyMaxPercent) {this._cleverActive = false} - if (energy / (width * height) <= Config.worldEnergyCheckPercent) { + if (energyPercent <= Config.worldEnergyCheckPercent) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); } } @@ -76,7 +72,7 @@ class Energy { if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._amount < 0) { this._lastX = this._lastY = -1; this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyPercent; + this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyBlockPercent; return; } @@ -85,6 +81,21 @@ class Energy { this._lastY = y + Helper.rand(3) - 1; if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex))} } + + _getEnergyPercent() { + let energy = 0; + const world = this._manager.world; + const width = Config.worldWidth; + const height = Config.worldHeight; + + for (let x = 0; x < width; x++) { + for (let y = 0; y < height; y++) { + if (world.getDot(x, y) > 0) {energy++} + } + } + + return energy / (width * height); + } } module.exports = Energy; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index c54e76f..1399289 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -20,7 +20,7 @@ const Config = { * onMyX,onMyY,onCheckLeft,onCheckRight,onCheckUp,onCheckDown * ] */ - orgOperatorWeights: [.1,.1,.1,.001,.1,.01,2.,2.,2.,2.,2.,2.,2.,2.,.1,.1,.1,.1,.1,.1,.1,.1], + orgOperatorWeights: [.00001,.00001,.00001,.0000001,.00001,.000001,.0002,.0002,.0002,.0002,.0002,.0002,.0002,.0002,.00001,.00001,.00001,.00001,.00001,.00001,.00001,.00001], /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of @@ -54,10 +54,6 @@ const Config = { * is not possible */ orgCloneMinEnergy: 10000, - /** - * {Number} Percent of energy, which will be grabbed from organism after clone - */ - orgCloneGrabEnergyPercent: .5, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing @@ -132,11 +128,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 2000, + orgMaxOrgs: 500, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 2000, + orgStartAmount: 500, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 61767e5..748a1ac 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -281,13 +281,7 @@ class Organisms extends Configurable { //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this.randOrg().destroy()} - if (this.organisms.size < OConfig.orgMaxOrgs && this._clone(org)) { - // - // Decrease amount of energy after clone from parent and child - // - org.energy *= (1 - OConfig.orgCloneGrabEnergyPercent); - this.organisms.last.val.energy *= (1 - OConfig.orgCloneGrabEnergyPercent); - } + this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); } _killInTour() { diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 868185f..fed5bd6 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -66,6 +66,20 @@ ClientConfig.init({ * calculations). */ worldCyclical: false, + /** + * {Number} Minimum percent of energy in current world. Under percent i mean + * percent from entire world area (100%). If the energy will be less + * or equal then this percent, then new random energy should be added. + * Should be less then 100.0 and more and equal to 0.0. 0.17 is a + * normal percent for this system. + */ + worldEnergyCheckPercent: 0.01, + /** + * {Number} An amount of iteration, after which we have to check world energy + * amount. Works in pair with worldEnergyCheckPercent. May be 0 if + * you want to disable it + */ + worldEnergyCheckPeriod: 5000, /** * {Number} Amount of energy blocks in a world. Blocks will be placed in a * random way... @@ -83,23 +97,22 @@ ClientConfig.init({ worldCleverEnergy: true, /** * {Number} size of one clever energy block (percent from world size). Calculates - * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyPercent + * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyBlockPercent */ - worldCleverEnergyPercent: 0.005, + worldCleverEnergyBlockPercent: 0.00001, /** - * {Number} Minimum percent of energy in current world. Under percent i mean - * percent from entire world area (100%). If the energy will be less - * or equal then this percent, then new random energy should be added. - * Should be less then 100.0 and more and equal to 0.0. 0.17 is a - * normal percent for this system. + * {Number} Percent from all energy in a world until clever energy will be added. + * After this value clever energy will be stopped to add until it's amount will + * be less then worldCleverEnergyMinPercent. These two configs create cyclical + * energy adding to the world. */ - worldEnergyCheckPercent: 0.05, + worldCleverEnergyMaxPercent: 0.1, /** - * {Number} An amount of iteration, after which we have to check world energy - * amount. Works in pair with worldEnergyCheckPercent. May be 0 if - * you want to disable it + * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from + * all energy in a world after which clever energy will turn on (be added to the + * world again). */ - worldEnergyCheckPeriod: 5000, + worldCleverEnergyMinPercent: 0.01, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index e7fa6c5..4f58dd7 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -101,7 +101,12 @@ class VM extends Observer { while (len > 0 && org.energy > 0) { operator = code[line] >>> OFFS; line = ops[operator](code[line], line, org, lines); - org.energy -= (this._weights[operator] * lines); + // + // This is very important peace of logic. As big the organism is + // as more energy he spends and as small his code is as less energy + // he spends + // + org.energy -= (this._weights[operator] * org.energy * (lines || 1)); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 2373223610890ccc30d92e2d8378a1a3f3ebcdc6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 12:26:22 +0200 Subject: [PATCH 207/291] fixed small format issue in Console plugin --- client/src/manager/plugins/status/console/Console.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index b4839f1..cfe5a14 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -47,7 +47,7 @@ class Console extends Status { const sips = format(status.ips, 'ips', 12); const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); - const senergy = format(status.energy, 'nrg', 17); + const senergy = format(status.energy, 'nrg', 19); const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); const skill = format(status.kill, 'kil', 12); From 49e5d85e1f2a3fd713942c58c11956f599d3f10f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 15:03:54 +0200 Subject: [PATCH 208/291] removed Organism.alive property. From now use org.energy > 0 check --- .../src/manager/plugins/organisms/Mutator.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 20 ++-- .../manager/plugins/organisms/Organisms.js | 14 +-- .../plugins/organisms/dos/OperatorsSpec.js | 38 +++--- .../manager/plugins/organisms/dos/Organism.js | 5 +- .../plugins/organisms/dos/OrganismSpec.js | 112 +++++++++--------- .../plugins/organisms/dos/Organisms.js | 7 +- .../plugins/organisms/garmin/Organism.js | 5 +- 8 files changed, 95 insertions(+), 108 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 55bf1ed..20c8044 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -106,7 +106,7 @@ class Mutator { } _onOrganism(org) { - if (org.iterations % org.mutationPeriod !== 0 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || !org.alive) {return} + if (org.iterations % org.mutationPeriod !== 0 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || org.energy < 1) {return} this._mutate(org); } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index d996ebe..1ec3208 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -70,13 +70,12 @@ class Organism extends Observer { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Function} operatorCls Class of operators * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, operatorCls, parent = null) { + constructor(id, x, y, item, operatorCls, parent = null) { super(EVENT_AMOUNT); this._operatorCls = operatorCls; @@ -88,7 +87,6 @@ class Organism extends Observer { this._y = y; this._iterations = -1; this._changes = 0; - this._alive = alive; this._item = item; this._fnId = 0; } @@ -96,7 +94,6 @@ class Organism extends Observer { get id() {return this._id} get x() {return this._x} get y() {return this._y} - get alive() {return this._alive} get item() {return this._item} get iterations() {return this._iterations} get changes() {return this._changes} @@ -126,12 +123,12 @@ class Organism extends Observer { run() { this._iterations++; if (this.onBeforeRun() === false) {return true} - const lines = this._alive ? this.onRun() : 0; - if (this._alive) { + const lines = this._energy > 0 ? this.onRun() : 0; + if (this._energy > 0) { this._updateClone(); - this._alive && this._updateEnergy(); - this._alive && this.fire(ITERATION, lines, this); - this._alive && this._updateAge(); + this._energy > 0 && this._updateEnergy(); + this._energy > 0 && this.fire(ITERATION, lines, this); + this._energy > 0 && this._updateAge(); } return true; @@ -147,7 +144,6 @@ class Organism extends Observer { x : this._x, y : this._y, changes : this._changes, - alive : this._alive, // 'item' will be added after insertion iterations : this._iterations, fnId : this._fnId, @@ -177,7 +173,6 @@ class Organism extends Observer { this._x = json.x; this._y = json.y; this._changes = json.changes; - this._alive = json.alive; // 'item' will be added after insertion this._iterations = json.iterations; this._fnId = json.fnId; @@ -203,7 +198,6 @@ class Organism extends Observer { destroy() { this.fire(DESTROY, this); - this._alive = false; this._energy = 0; this._startEnergy = 0; this._item = null; @@ -249,7 +243,7 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0 && this._alive) { + if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0 && this._energy > 0) { this.fire(CLONE, this); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 748a1ac..2aefa1b 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -189,7 +189,7 @@ class Organisms extends Configurable { while (org = item && item.val) { org.run(); - org.alive && this.onOrganism(org); + org.energy > 0 && this.onOrganism(org); item = item.next; } @@ -206,8 +206,8 @@ class Organisms extends Configurable { org1 = org1 || this.randOrg(); org2 = org2 || this.randOrg(); - if (!org1.alive && !org2.alive) {return false} - if ((org2.alive && !org1.alive) || this.compare(org2, org1)) { + if (org1.energy < 1 && org2.energy < 1) {return false} + if ((org2.energy > 0 && org1.energy < 1) || this.compare(org2, org1)) { return org2; } @@ -221,7 +221,7 @@ class Organisms extends Configurable { let child = this.organisms.last.val; this.onClone(org, child); - if (!org.alive || !child.alive) {return false} + if (org.energy < 1 || child.energy < 1) {return false} this.parent.fire(EVENTS.CLONE, org, child, isCrossover); return true; @@ -232,7 +232,7 @@ class Organisms extends Configurable { const orgs = this.organisms; let child = orgs.last.val; - if (child.alive && org2.alive) { + if (child.energy > 0 && org2.energy > 0) { child.changes += (Math.abs(child.vm.crossover(org2.vm)) * Num.MAX_BITS); } } @@ -287,7 +287,7 @@ class Organisms extends Configurable { _killInTour() { let org1 = this.randOrg(); let org2 = this.randOrg(); - if (!org1.alive || !org2.alive || org1 === org2 || this.organisms.size < 1) {return false} + if (org1.energy < 1 || org2.energy < 1 || org1 === org2 || this.organisms.size < 1) {return false} if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} this.parent.fire(EVENTS.KILL_TOUR, org2); @@ -328,7 +328,7 @@ class Organisms extends Configurable { let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - if (!org1.alive || !org2.alive) {return false} + if (org1.energy < 1 || org2.energy < 1) {return false} this._crossover(org1, org2); if (orgAmount + 1 >= OConfig.orgMaxOrgs) { if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 8666ef9..9a24191 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -3,9 +3,7 @@ describe("client/src/organism/OperatorsDos", () => { let cbpv = OConfig.codeBitsPerVar; OConfig.codeBitsPerVar = 2; let OperatorsDos = require('./Operators'); - let Observer = require('./../../../../../../common/src/Observer'); let EVENTS = require('./../../../../share/Events').EVENTS; - let EVENT_AMOUNT = require('./../../../../share/Events').EVENT_AMOUNT; let Config = require('./../../../../share/Config').Config; let OrganismDos = require('./../../organisms/dos/Organism'); //let OEvents = require('./../../organisms/Organism').EVENTS; @@ -17,7 +15,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking variables working", () => { @@ -62,7 +60,7 @@ describe("client/src/organism/OperatorsDos", () => { let codeConstBits = OConfig.codeConstBits; OConfig.codeConstBits = 16; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); afterAll (() => OConfig.codeConstBits = codeConstBits); @@ -102,7 +100,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking conditions", () => { @@ -143,7 +141,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking conditions", () => { @@ -184,7 +182,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking onOperator() method", () => { @@ -254,7 +252,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking onLookAt() is found nothing", () => { @@ -322,7 +320,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking eating nothing", () => { @@ -383,7 +381,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking eating nothing", () => { @@ -444,7 +442,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking eating nothing", () => { @@ -505,7 +503,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking eating nothing", () => { @@ -566,7 +564,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking step left", () => { @@ -628,7 +626,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking step right", () => { @@ -690,7 +688,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking step up", () => { @@ -752,7 +750,7 @@ describe("client/src/organism/OperatorsDos", () => { const w = Config.worldWidth; const h = Config.worldHeight; - beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {Config.worldHeight = Config.worldWidth = 10;org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy(); Config.worldHeight = h; Config.worldWidth = w}); it("Checking step down", () => { @@ -813,7 +811,7 @@ describe("client/src/organism/OperatorsDos", () => { let ops; let mbits; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); beforeAll(() => {mbits = OConfig.orgMemBits; OConfig.orgMemBits = 2}); afterAll(() => OConfig.orgMemBits = mbits); @@ -873,7 +871,7 @@ describe("client/src/organism/OperatorsDos", () => { let ops; let mbits; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([1], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); beforeAll(() => {mbits = OConfig.orgMemBits; OConfig.orgMemBits = 2}); afterAll(() => OConfig.orgMemBits = mbits); @@ -908,7 +906,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking simple values", () => { @@ -947,7 +945,7 @@ describe("client/src/organism/OperatorsDos", () => { let org; let ops; - beforeEach(() => {org = new OrganismDos('0', 0, 0, true, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); it("Checking simple values", () => { diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index 7ba1446..db11544 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -14,13 +14,12 @@ class OrganismDos extends Organism { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, parent = null) { - super(id, x, y, alive, item, Operators, parent); + constructor(id, x, y, item, parent = null) { + super(id, x, y, item, Operators, parent); } onRun() { diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 08d12f7..17c7589 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -6,15 +6,18 @@ describe("client/src/organism/OrganismDos", () => { const OrganismDos = require('./Organism'); const OConfig = require('./../../../../manager/plugins/organisms/Config'); + let org; + + beforeEach(() => org = new OrganismDos('0', 1, 2, null)); + afterEach (() => org.destroy()); + describe('Organism creation', () => { it("Checking organism creation", () => { - let org = new OrganismDos('0', 1, 2, true, null); - expect(org.id).toEqual('0'); expect(org.x).toEqual(1); expect(org.y).toEqual(2); expect(org.item).toEqual(null); - expect(org.alive).toEqual(true); + expect(org.energy > 0).toEqual(true); expect(org.mutationProbs).toEqual(OConfig.orgMutationProbs); expect(org.mutationProbs !== OConfig.orgMutationProbs).toEqual(true); expect(org.mutationPeriod === OConfig.orgRainMutationPeriod).toEqual(true); @@ -24,13 +27,11 @@ describe("client/src/organism/OrganismDos", () => { expect(org.changes).toBe(0); expect(org.energy).toBe(OConfig.orgStartEnergy); expect(org.iterations).toBe(-1); - - org.destroy(); }); it("Checking organism creation from parent", () => { const memSize = OConfig.orgMemBits; - const parent = new OrganismDos('1', 3, 4, true, null); + const parent = new OrganismDos('1', 3, 4, null); OConfig.orgMemBits = 2; parent.vm.insertLine(); @@ -41,50 +42,49 @@ describe("client/src/organism/OrganismDos", () => { parent.mutationPercent = 0.2; parent.mem.splice(0, parent.mem.length, ...[1,2,4,3]); - let org = new OrganismDos('0', 1, 2, true, null, parent); - - expect(org.vm.code).toEqual(parent.vm.code); - expect(org.vm.size).toEqual(parent.vm.size); - expect(org.energy).toEqual(parent.energy); - expect(org.color).toEqual(parent.color); - expect(org.mutationProbs).toEqual(parent.mutationProbs); - expect(org.mutationPeriod).toEqual(parent.mutationPeriod); - expect(org.mutationPercent).toEqual(parent.mutationPercent); - expect(org.mem).toEqual(parent.mem); - expect(org.changes).toEqual(0); - expect(org.iterations).toEqual(-1); - expect(org.alive).toEqual(true); - expect(org.item).toEqual(null); - - org.destroy(); + let org1 = new OrganismDos('0', 1, 2, null, parent); + + expect(org1.vm.code).toEqual(parent.vm.code); + expect(org1.vm.size).toEqual(parent.vm.size); + expect(org1.energy).toEqual(parent.energy); + expect(org1.color).toEqual(parent.color); + expect(org1.mutationProbs).toEqual(parent.mutationProbs); + expect(org1.mutationPeriod).toEqual(parent.mutationPeriod); + expect(org1.mutationPercent).toEqual(parent.mutationPercent); + expect(org1.mem).toEqual(parent.mem); + expect(org1.changes).toEqual(0); + expect(org1.iterations).toEqual(-1); + expect(org1.energy > 0).toEqual(true); + expect(org1.item).toEqual(null); + + org1.destroy(); OConfig.orgMemBits = memSize; }); }); - it("Checking if organism if alive", () => { - let org = new OrganismDos('0', 1, 2, true, null); - const period = OConfig.orgAlivePeriod; - const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; - - OConfig.orgAlivePeriod = 100; - OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 100; - - expect(org.alive).toEqual(true); - org.run(); - expect(org.alive).toEqual(true); - - expect(org.alive).toEqual(true); - OConfig.orgAlivePeriod = period; - OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; + describe('Checking organism alive', () => { + it("Organism should be dead after loosing all energy", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + const speriod = OConfig.orgEnergySpendPeriod; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; + OConfig.orgEnergySpendPeriod = 100; + const org1 = new OrganismDos('0', 1, 2, null); + + expect(org1.energy > 0).toBe(true); + org.run(); + expect(org1.energy > 0).toBe(true); - org.destroy(); + org1.destroy(); + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = speriod; + }); }); it("Checking organism changes", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); expect(org.changes).toEqual(1); org.changes = 10; @@ -96,7 +96,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking run() method", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); expect(org.iterations).toEqual(0); org.run(); @@ -109,14 +109,14 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of age", () => { const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); OConfig.orgAlivePeriod = 30000; for (let i = 0; i < OConfig.orgAlivePeriod; i++) { - expect(org.alive).toEqual(true); + expect(org.energy > 0).toEqual(true); org.run(); } - expect(org.alive).toEqual(false); + expect(org.energy > 0).toEqual(false); // we don't need to call destroy, because organism // should be dead at this moment OConfig.orgAlivePeriod = period; @@ -124,14 +124,14 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of zero energy", () => { const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); OConfig.orgAlivePeriod = 30000; expect(org.energy).toEqual(OConfig.orgStartEnergy); org.energy = 0; - expect(org.alive).toEqual(true); + expect(org.energy > 0).toEqual(true); org.run(); - expect(org.alive).toEqual(false); + expect(org.energy > 0).toEqual(false); // we don't need to call destroy, because organism // should be dead at this moment OConfig.orgAlivePeriod = period; @@ -139,13 +139,13 @@ describe("client/src/organism/OrganismDos", () => { it("Checking organism destroy because of grab energy", () => { const period = OConfig.orgEnergySpendPeriod; - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); OConfig.orgEnergySpendPeriod = 1; org.energy = 1; - expect(org.alive).toEqual(true); + expect(org.energy > 0).toEqual(true); org.run(); - expect(org.alive).toEqual(false); + expect(org.energy > 0).toEqual(false); // // we don't need to call destroy, because organism // should be dead at this moment @@ -154,7 +154,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking grabbing energy", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); const energy = org.energy; org.energy -= 10; @@ -164,7 +164,7 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking organism color change", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); const color = org.color; org.changes = 10; @@ -174,12 +174,10 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking destroy() method", () => { - let org = new OrganismDos(0, 1, 2, true, null, () => {}); + let org = new OrganismDos(0, 1, 2, null, () => {}); - expect(org.alive).toEqual(true); expect(org.energy > 0).toEqual(true); org.destroy(); - expect(org.alive).toEqual(false); expect(org.energy > 0).toEqual(false); }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 144081f..ac1872f 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -12,7 +12,6 @@ */ const BaseOrganisms = require('./../Organisms'); const Organism = require('./Organism'); -const OEVENTS = require('./../Organism').EVENTS; const Config = require('./../../../../share/Config').Config; const OConfig = require('./../Config'); const EVENTS = require('./../../../../share/Events').EVENTS; @@ -95,8 +94,8 @@ class Organisms extends BaseOrganisms { org.energy -= energy; childEnergy <= (childEnergy - energy) && this.parent.fire(EVENTS.KILL_CLONE, child); child.energy -= (childEnergy - energy); - org.alive && (org.startEnergy = org.energy); - child.alive && (child.startEnergy = child.energy); + org.energy > 0 && (org.startEnergy = org.energy); + child.energy > 0 && (child.startEnergy = child.energy); } addOrgHandlers(org) { @@ -184,7 +183,7 @@ class Organisms extends BaseOrganisms { } _onStep(org, x1, y1, x2, y2, ret) { - if (org.alive === false) {return} + if (org.energy < 1) {return} const man = this.parent; let dir; diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index 590d476..2ed9a63 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -16,14 +16,13 @@ class OrganismGarmin extends Organism { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Boolean} alive true if organism is alive * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Observer} obs Observer for sending external events * @param {Organism} parent Parent organism if cloning is needed */ - constructor(id, x, y, alive, item, obs, parent = null) { - super(id, x, y, alive, item, Operators, obs, parent); + constructor(id, x, y, item, obs, parent = null) { + super(id, x, y, item, Operators, obs, parent); this._needRun = true; From 6d7a1c03d436893cc026ca2502c4bc5d1eb47201 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 15:46:29 +0200 Subject: [PATCH 209/291] added more tests #83 --- .../plugins/organisms/dos/OrganismSpec.js | 105 +++++++++++++++++- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 17c7589..0627e99 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -63,7 +63,7 @@ describe("client/src/organism/OrganismDos", () => { }); describe('Checking organism alive', () => { - it("Organism should be dead after loosing all energy", () => { + it("Organism should not be dead after loosing some energy", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; const speriod = OConfig.orgEnergySpendPeriod; @@ -72,11 +72,108 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgEnergySpendPeriod = 100; const org1 = new OrganismDos('0', 1, 2, null); - expect(org1.energy > 0).toBe(true); - org.run(); - expect(org1.energy > 0).toBe(true); + expect(org1.energy).toBe(100); + org1.run(); + expect(org1.energy).toBe(99); + org1.run(); + expect(org1.energy).toBe(99); + org1.destroy(); + expect(org1.energy < 1).toBe(true); + + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = speriod; + }); + + it("Organism should not be dead after loosing some energy 2", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + const speriod = OConfig.orgEnergySpendPeriod; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; + OConfig.orgEnergySpendPeriod = 1; + const org1 = new OrganismDos('0', 1, 2, null); + + expect(org1.energy).toBe(100); + org1.run(); + expect(org1.energy).toBe(99); + org1.run(); + expect(org1.energy).toBe(98); + org1.destroy(); + expect(org1.energy < 1).toBe(true); + + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = speriod; + }); + + it("Organism should not be dead after loosing some energy 3", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + const speriod = OConfig.orgEnergySpendPeriod; + const weights = OConfig.orgOperatorWeights.slice(); + const yieldPeriod = OConfig.codeYieldPeriod; + const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; + OConfig.orgEnergySpendPeriod = 1; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + OConfig.codeYieldPeriod = 1; + const org1 = new OrganismDos('0', 1, 2, null); + org1.vm.insertLine(); + + expect(org1.energy).toBe(100); + org1.run(); + expect(org1.energy).toBe(89); // 100 - 100 * .1 - 1 = 89 + org1.run(); + expect(org1.energy).toBe(79.1); // 89 - 89 * .1 - 1 = 79.1 + org1.destroy(); + expect(org1.energy < 1).toBe(true); + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = speriod; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + OConfig.codeYieldPeriod = yieldPeriod; + }); + + it("Organism should not be dead if loosing energy is turned off", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + const speriod = OConfig.orgEnergySpendPeriod; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; + OConfig.orgEnergySpendPeriod = 0; + const org1 = new OrganismDos('0', 1, 2, null); + + expect(org1.energy).toBe(100); + org1.run(); + expect(org1.energy).toBe(100); + org1.run(); + expect(org1.energy).toBe(100); org1.destroy(); + expect(org1.energy < 1).toBe(true); + + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = speriod; + }); + + it("Organism should do nothing if energy is set to zero", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + const speriod = OConfig.orgEnergySpendPeriod; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; + OConfig.orgEnergySpendPeriod = 0; + const org1 = new OrganismDos('0', 1, 2, null); + + expect(org1.energy).toBe(100); + org1.energy = 0; + org1.run(); + expect(org1.energy).toBe(0); + org1.destroy(); + OConfig.orgAlivePeriod = period; OConfig.orgStartEnergy = energy; OConfig.orgEnergySpendPeriod = speriod; From b3c53faa3871321e2f421b9875f74ca49a4892d0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 16:24:50 +0200 Subject: [PATCH 210/291] added more tests #83 --- .../plugins/organisms/dos/OrganismSpec.js | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 0627e99..ddc5907 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -180,16 +180,23 @@ describe("client/src/organism/OrganismDos", () => { }); }); - it("Checking organism changes", () => { - let org = new OrganismDos(0, 1, 2, null, () => {}); - - expect(org.changes).toEqual(1); - org.changes = 10; - expect(org.changes).toEqual(10); - org.changes += 12; - expect(org.changes).toEqual(22); + describe('Changes check', () => { + it("Checking organism changes", () => { + expect(org.changes).toBe(0); + org.changes = 10; + expect(org.changes).toBe(10); + org.changes += 12; + expect(org.changes).toBe(22); + }); - org.destroy(); + it("Checking if changes affect color", () => { + const color = org.color; + const colorIndex = org.colorIndex; + expect(org.changes).toBe(0); + org.changes = 10; + expect(org.color).not.toBe(color); + expect(org.colorIndex).not.toBe(colorIndex); + }); }); it("Checking run() method", () => { From 577b8a0470042f6cc299f844d7f0a7777e261643 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 20:00:10 +0200 Subject: [PATCH 211/291] removed unused code --- .../manager/plugins/organisms/Organisms.js | 23 ++++++------------- client/src/share/Config.js | 8 +++---- common/src/Observer.js | 3 ++- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 748a1ac..ac1492d 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -73,6 +73,13 @@ class Organisms extends Configurable { */ createEmptyOrg(...args) {} + /** + * Is called at the end of run() method + * @param {Organism} org Current organism + * @abstract + */ + onOrganism(org) {} + constructor(manager) { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; @@ -81,8 +88,6 @@ class Organisms extends Configurable { this.world = manager.world; this._mutator = new Mutator(manager, this); - this._maxEnergy = 0; - this._oldMaxEnergy = 0; this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -106,20 +111,6 @@ class Organisms extends Configurable { super.destroy(); } - /** - * Is called at the end of run() method - * @param {Organism} org Current organism - */ - onOrganism(org) { - const energy = org.energy / org.vm.size; - if (energy > this._oldMaxEnergy) {this._oldMaxEnergy = energy} - - if (org === this.organisms.last.val) { - this._maxEnergy = this._oldMaxEnergy; - this._oldMaxEnergy = 0; - } - } - addOrgHandlers(org) { org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index fed5bd6..6cdc354 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -73,7 +73,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.01, + worldEnergyCheckPercent: 0.001, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if @@ -99,20 +99,20 @@ ClientConfig.init({ * {Number} size of one clever energy block (percent from world size). Calculates * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyBlockPercent */ - worldCleverEnergyBlockPercent: 0.00001, + worldCleverEnergyBlockPercent: 0.00004, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will * be less then worldCleverEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMaxPercent: 0.1, + worldCleverEnergyMaxPercent: 0.04, /** * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.01, + worldCleverEnergyMinPercent: 0.02, /** * {Number} Zoom speed 0..1 */ diff --git a/common/src/Observer.js b/common/src/Observer.js index 4f5bd66..85948a2 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -62,7 +62,8 @@ class Observer { */ fire(event, ...args) { const handlers = this._handlers[event]; - for (let i = 0, len = handlers.amount; i < len; i++) { + const len = handlers.amount; + for (let i = 0; i < len; i++) { handlers[i](...args); } } From ad854bf1cdac29b3b6c9ac28e9d07ba6ee9bdeaf Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 20:32:32 +0200 Subject: [PATCH 212/291] fixed many small issues after refactoring --- client/src/manager/plugins/organisms/Organism.js | 11 ++++++++--- .../src/manager/plugins/organisms/Organisms.js | 16 ++++++++++------ 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 1ec3208..104b32d 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -124,9 +124,9 @@ class Organism extends Observer { this._iterations++; if (this.onBeforeRun() === false) {return true} const lines = this._energy > 0 ? this.onRun() : 0; + this._updateEnergy(); if (this._energy > 0) { this._updateClone(); - this._energy > 0 && this._updateEnergy(); this._energy > 0 && this.fire(ITERATION, lines, this); this._energy > 0 && this._updateAge(); } @@ -271,8 +271,13 @@ class Organism extends Observer { */ _updateEnergy() { if (this._energy < 1) { - this.fire(KILL_NO_ENERGY, this); - this.destroy(); + // + // We have to destroy organism only if he hasn't destroyed yet + // + if (this.vm) { + this.fire(KILL_NO_ENERGY, this); + this.destroy(); + } return true; } if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 4dd8208..3e4a9d7 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -140,7 +140,7 @@ class Organisms extends Configurable { const orgs = this.organisms; orgs.add(null); let last = orgs.last; - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, true, last, parent); + let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, last, parent); last.val = org; this.addOrgHandlers(org); @@ -276,11 +276,13 @@ class Organisms extends Configurable { } _killInTour() { - let org1 = this.randOrg(); - let org2 = this.randOrg(); + let org1 = this.randOrg(); + let org2 = this.randOrg(); if (org1.energy < 1 || org2.energy < 1 || org1 === org2 || this.organisms.size < 1) {return false} + const winner = this._tournament(org1, org2); + if (winner === false) {return false} - if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + if (winner === org2) {[org1, org2] = [org2, org1]} this.parent.fire(EVENTS.KILL_TOUR, org2); org2.destroy(); @@ -319,10 +321,12 @@ class Organisms extends Configurable { let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - if (org1.energy < 1 || org2.energy < 1) {return false} + if (org1 === false || org2 === false || org1.energy < 1 || org2.energy < 1) {return false} this._crossover(org1, org2); if (orgAmount + 1 >= OConfig.orgMaxOrgs) { - if (this._tournament(org1, org2) === org2) {[org1, org2] = [org2, org1]} + const winner = this._tournament(org1, org2); + if (winner === false) {return false} + if (winner === org2) {[org1, org2] = [org2, org1]} this.parent.fire(EVENTS.KILL_OVERFLOW, org2); org2.destroy(); } From 99d5d057474ca021027dab49298ef71009997f05 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 22:56:48 +0200 Subject: [PATCH 213/291] fixing tests... #83 removed decreasing energy depending on organism size --- .../src/manager/plugins/organisms/Config.js | 5 --- .../src/manager/plugins/organisms/Organism.js | 24 ++++------- .../plugins/organisms/dos/OrganismSpec.js | 43 +++---------------- .../plugins/organisms/dos/Organisms.js | 2 +- client/src/vm/VM.js | 5 +-- 5 files changed, 18 insertions(+), 61 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 1399289..9021baa 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -93,11 +93,6 @@ const Config = { * to turn off this feature */ orgRandomOrgPeriod: 0, - /** - * {Number} Amount of iterations within organism's life loop, after that we decrease - * some amount of energy. If 0, then energy decreasing will be disabled. - */ - orgEnergySpendPeriod: 0, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 104b32d..54d3eff 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -265,27 +265,19 @@ class Organism extends Observer { } /** - * This is how our system grabs an energy from organism every OConfig.orgEnergySpendPeriod - * period. If organism has zero energy, it will be killed also. + * This method destroys organisms with zero energy * @return {Boolean} false means that organism was destroyed. */ _updateEnergy() { - if (this._energy < 1) { - // - // We have to destroy organism only if he hasn't destroyed yet - // - if (this.vm) { - this.fire(KILL_NO_ENERGY, this); - this.destroy(); - } - return true; + // + // this.vm === null means, that organism has already destroyed + // + if (this._energy < 1 && this.vm) { + this.fire(KILL_NO_ENERGY, this); + this.destroy(); } - if (this._iterations % OConfig.orgEnergySpendPeriod !== 0 || OConfig.orgEnergySpendPeriod === 0) {return true} - let grabSize = this.vm.size; - if (grabSize < 1) {grabSize = 1} - (this._energy <= grabSize) && this.fire(KILL_NO_ENERGY, this); - return this._energy -= (this._energy < grabSize ? this._energy : grabSize); + return true; } } diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index ddc5907..b709520 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -63,60 +63,32 @@ describe("client/src/organism/OrganismDos", () => { }); describe('Checking organism alive', () => { - it("Organism should not be dead after loosing some energy", () => { + it("Organism should not be dead it he doesn't contain code", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; - OConfig.orgAlivePeriod = 100; - OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 100; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; const org1 = new OrganismDos('0', 1, 2, null); expect(org1.energy).toBe(100); org1.run(); - expect(org1.energy).toBe(99); - org1.run(); - expect(org1.energy).toBe(99); - org1.destroy(); - expect(org1.energy < 1).toBe(true); - - OConfig.orgAlivePeriod = period; - OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; - }); - - it("Organism should not be dead after loosing some energy 2", () => { - const period = OConfig.orgAlivePeriod; - const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; - OConfig.orgAlivePeriod = 100; - OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 1; - const org1 = new OrganismDos('0', 1, 2, null); - expect(org1.energy).toBe(100); - org1.run(); - expect(org1.energy).toBe(99); - org1.run(); - expect(org1.energy).toBe(98); org1.destroy(); expect(org1.energy < 1).toBe(true); - OConfig.orgAlivePeriod = period; - OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; }); - it("Organism should not be dead after loosing some energy 3", () => { + + it("Organism should not be dead after loosing some energy", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; const weights = OConfig.orgOperatorWeights.slice(); const yieldPeriod = OConfig.codeYieldPeriod; const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; OConfig.orgAlivePeriod = 100; OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 1; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); OConfig.codeYieldPeriod = 1; const org1 = new OrganismDos('0', 1, 2, null); @@ -132,7 +104,6 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgAlivePeriod = period; OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); OConfig.codeYieldPeriod = yieldPeriod; }); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index ac1872f..bb15aca 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -161,7 +161,7 @@ class Organisms extends BaseOrganisms { // Amount of eat energy depends on organism size. Small organisms // eat less, big - more // - const eat = ret.ret / ((OConfig.codeMaxSize / (org.vm.size || 1)) || 1); + const eat = ret.ret; [x, y] = NORMALIZE_NO_DIR(x, y); const posId = POSID(x, y); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 4f58dd7..5bb5c3a 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -103,10 +103,9 @@ class VM extends Observer { line = ops[operator](code[line], line, org, lines); // // This is very important peace of logic. As big the organism is - // as more energy he spends and as small his code is as less energy - // he spends + // as more energy he spends // - org.energy -= (this._weights[operator] * org.energy * (lines || 1)); + org.energy -= (this._weights[operator] * org.energy); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 676819f84d9351275a7da6017a0cf9569a4efa82 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 21 Feb 2018 22:57:37 +0200 Subject: [PATCH 214/291] fixing tests #83 --- client/src/manager/plugins/organisms/dos/OrganismSpec.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index ddc5907..d81caac 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -159,7 +159,7 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgEnergySpendPeriod = speriod; }); - it("Organism should do nothing if energy is set to zero", () => { + it("Organism should be destroyed on run if energy is set to zero", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; const speriod = OConfig.orgEnergySpendPeriod; @@ -171,8 +171,8 @@ describe("client/src/organism/OrganismDos", () => { expect(org1.energy).toBe(100); org1.energy = 0; org1.run(); - expect(org1.energy).toBe(0); - org1.destroy(); + expect(org1.vm).toBe(null); + org1.run(); OConfig.orgAlivePeriod = period; OConfig.orgStartEnergy = energy; @@ -189,7 +189,7 @@ describe("client/src/organism/OrganismDos", () => { expect(org.changes).toBe(22); }); - it("Checking if changes affect color", () => { + it("Checking if changes affects color", () => { const color = org.color; const colorIndex = org.colorIndex; expect(org.changes).toBe(0); From f6dc9244f30ddb8ffe8c3c2f6a4a8102928b0185 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 00:04:18 +0200 Subject: [PATCH 215/291] added more tests #83 --- .../src/manager/plugins/organisms/Organism.js | 1 + .../plugins/organisms/dos/OrganismSpec.js | 163 +++++++++--------- 2 files changed, 83 insertions(+), 81 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 54d3eff..83edc61 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -197,6 +197,7 @@ class Organism extends Observer { } destroy() { + if (this.vm === null) {return} this.fire(DESTROY, this); this._energy = 0; this._startEnergy = 0; diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 8ef9f1b..672b344 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -4,7 +4,9 @@ describe("client/src/organism/OrganismDos", () => { const _fill = require('lodash/fill'); const OrganismDos = require('./Organism'); + const OEvents = require('./../Organism').EVENTS; const OConfig = require('./../../../../manager/plugins/organisms/Config'); + const Helper = require('./../../../../../../common/src/Helper'); let org; @@ -96,9 +98,9 @@ describe("client/src/organism/OrganismDos", () => { expect(org1.energy).toBe(100); org1.run(); - expect(org1.energy).toBe(89); // 100 - 100 * .1 - 1 = 89 + expect(org1.energy).toBe(90); // 100 - 100 * .1 = 90 org1.run(); - expect(org1.energy).toBe(79.1); // 89 - 89 * .1 - 1 = 79.1 + expect(org1.energy).toBe(81); // 90 - 90 * .1 = 81 org1.destroy(); expect(org1.energy < 1).toBe(true); @@ -111,10 +113,8 @@ describe("client/src/organism/OrganismDos", () => { it("Organism should not be dead if loosing energy is turned off", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; - OConfig.orgAlivePeriod = 100; - OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 0; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; const org1 = new OrganismDos('0', 1, 2, null); expect(org1.energy).toBe(100); @@ -125,18 +125,15 @@ describe("client/src/organism/OrganismDos", () => { org1.destroy(); expect(org1.energy < 1).toBe(true); - OConfig.orgAlivePeriod = period; - OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; }); it("Organism should be destroyed on run if energy is set to zero", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; - const speriod = OConfig.orgEnergySpendPeriod; - OConfig.orgAlivePeriod = 100; - OConfig.orgStartEnergy = 100; - OConfig.orgEnergySpendPeriod = 0; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; const org1 = new OrganismDos('0', 1, 2, null); expect(org1.energy).toBe(100); @@ -145,9 +142,8 @@ describe("client/src/organism/OrganismDos", () => { expect(org1.vm).toBe(null); org1.run(); - OConfig.orgAlivePeriod = period; - OConfig.orgStartEnergy = energy; - OConfig.orgEnergySpendPeriod = speriod; + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; }); }); @@ -170,82 +166,87 @@ describe("client/src/organism/OrganismDos", () => { }); }); - it("Checking run() method", () => { - let org = new OrganismDos(0, 1, 2, null, () => {}); - - expect(org.iterations).toEqual(0); - org.run(); - expect(org.iterations).toEqual(1); - org.run(); - expect(org.iterations).toEqual(2); + describe('Checks coordinates', () => { + it('posId() should return unique hash', () => { + org.x = 2; + org.y = 3; + expect(org.posId).toBe(Helper.posId(2, 3)); + org.x = 0; + org.y = 3; + expect(org.posId).toBe(Helper.posId(0, 3)); + }); - org.destroy(); + it('Checks coordinates setters getters', () => { + org.x = 1; + org.y = 2; + expect(org.x).toBe(1); + expect(org.y).toBe(2); + org.x = 0; + org.y = 0; + expect(org.x).toBe(0); + expect(org.y).toBe(0); + org.x = -1; + org.y = -2; + expect(org.x).toBe(-1); + expect(org.y).toBe(-2); + }) }); - it("Checking organism destroy because of age", () => { - const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, null, () => {}); + describe('run() method', () => { + it("Organism's age should be changed through iterations", () => { + const period = OConfig.orgAlivePeriod; + const energy = OConfig.orgStartEnergy; + OConfig.orgAlivePeriod = 100; + OConfig.orgStartEnergy = 100; - OConfig.orgAlivePeriod = 30000; - for (let i = 0; i < OConfig.orgAlivePeriod; i++) { - expect(org.energy > 0).toEqual(true); + expect(org.iterations).toEqual(-1); org.run(); - } - expect(org.energy > 0).toEqual(false); - // we don't need to call destroy, because organism - // should be dead at this moment - OConfig.orgAlivePeriod = period; - }); - - it("Checking organism destroy because of zero energy", () => { - const period = OConfig.orgAlivePeriod; - let org = new OrganismDos(0, 1, 2, null, () => {}); - - OConfig.orgAlivePeriod = 30000; - expect(org.energy).toEqual(OConfig.orgStartEnergy); - org.energy = 0; - expect(org.energy > 0).toEqual(true); - org.run(); - expect(org.energy > 0).toEqual(false); - // we don't need to call destroy, because organism - // should be dead at this moment - OConfig.orgAlivePeriod = period; - }); - - it("Checking organism destroy because of grab energy", () => { - const period = OConfig.orgEnergySpendPeriod; - let org = new OrganismDos(0, 1, 2, null, () => {}); - - OConfig.orgEnergySpendPeriod = 1; - org.energy = 1; - expect(org.energy > 0).toEqual(true); - org.run(); - expect(org.energy > 0).toEqual(false); - // - // we don't need to call destroy, because organism - // should be dead at this moment - // - OConfig.orgEnergySpendPeriod = period; - }); - - it("Checking grabbing energy", () => { - let org = new OrganismDos(0, 1, 2, null, () => {}); - const energy = org.energy; + expect(org.iterations).toEqual(0); + org.run(); + expect(org.iterations).toEqual(1); - org.energy -= 10; - expect(org.energy).toEqual(energy - 10); + OConfig.orgAlivePeriod = period; + OConfig.orgStartEnergy = energy; + }); - org.destroy(); + it("Checking organism destroy because of age", () => { + const period = OConfig.orgAlivePeriod; + + OConfig.orgAlivePeriod = 3000; + for (let i = 0; i < OConfig.orgAlivePeriod + 1; i++) { + expect(org.energy > 0).toBe(true); + org.run(); + } + expect(org.energy < 1).toEqual(true); + // we don't need to call destroy, because organism + // should be dead at this moment + OConfig.orgAlivePeriod = period; + }); }); - it("Checking organism color change", () => { - let org = new OrganismDos(0, 1, 2, null, () => {}); - const color = org.color; + describe('Clonning', () => { + it('Organism should fire CLONE event if enough energy', () => { + let flag = false; + const minEnergy = OConfig.orgCloneMinEnergy; + const yieldPeriod = OConfig.codeYieldPeriod; + const weights = OConfig.orgOperatorWeights.slice(); + const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + OConfig.orgCloneMinEnergy = 100; + OConfig.codeYieldPeriod = 1; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + const org1 = new OrganismDos('0', 1, 2, null); - org.changes = 10; - expect(org.color).toEqual(color + 10); + org1.vm.insertLine(); + org1.energy = OConfig.orgCloneMinEnergy * 2; + org1.on(OEvents.CLONE, () => flag = true); + org1.run(); + expect(flag).toBe(true); - org.destroy(); + org1.destroy(); + OConfig.orgCloneMinEnergy = minEnergy; + OConfig.codeYieldPeriod = yieldPeriod; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + }) }); it("Checking destroy() method", () => { From 7bd6ebc62edea44b6b62d1375d2558bcfc8cf99c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 00:29:13 +0200 Subject: [PATCH 216/291] small refactoring --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/organisms/Organism.js | 2 +- client/src/vm/VM.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 9021baa..ca108e1 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -53,7 +53,7 @@ const Config = { * If amount of energy less then orgCloneMinEnergy * vm.size, then clone * is not possible */ - orgCloneMinEnergy: 10000, + orgCloneMinEnergy: 500000, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 83edc61..da46d1c 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -244,7 +244,7 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > OConfig.orgCloneMinEnergy * (this.vm.size || 1)) && this.vm.size > 0 && this._energy > 0) { + if (this._energy > OConfig.orgCloneMinEnergy && this._energy > 0) { this.fire(CLONE, this); } } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 5bb5c3a..67f8caf 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -58,7 +58,6 @@ class VM extends Observer { get size() {return this._code.length} get operators() {return this._operators} get vars() {return this._vars} - get offsets() {return this._offsets} get line() {return this._line} serialize() { From 855fe8d52d61a50427ea1f633d1f8f0e837429c4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 01:00:51 +0200 Subject: [PATCH 217/291] small refactoring --- client/src/manager/plugins/organisms/Organisms.js | 7 ++++++- client/src/share/Config.js | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 3e4a9d7..aca2f10 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -272,7 +272,12 @@ class Organisms extends Configurable { //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this.randOrg().destroy()} - this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); + // if (this.organisms.size >= OConfig.orgMaxOrgs && Math.random() <= ((org.energy / 10000000000000) * (org.iterations / OConfig.orgAlivePeriod))) { + // this.randOrg().destroy(); + // } + if (this.organisms.size < OConfig.orgMaxOrgs) { + this._clone(org); + } } _killInTour() { diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 6cdc354..e95639d 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -99,20 +99,20 @@ ClientConfig.init({ * {Number} size of one clever energy block (percent from world size). Calculates * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyBlockPercent */ - worldCleverEnergyBlockPercent: 0.00004, + worldCleverEnergyBlockPercent: 0.00002, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will * be less then worldCleverEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMaxPercent: 0.04, + worldCleverEnergyMaxPercent: 0.03, /** * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.02, + worldCleverEnergyMinPercent: 0.15, /** * {Number} Zoom speed 0..1 */ From 084e9c404c7976bace3d430e6f2b76480e5f23f1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 16:18:01 +0200 Subject: [PATCH 218/291] testing new approach of selection/survival --- client/src/manager/plugins/organisms/Config.js | 15 ++++++++------- client/src/manager/plugins/organisms/Organism.js | 2 +- client/src/manager/plugins/organisms/Organisms.js | 7 +++++-- client/src/share/Config.js | 4 ++-- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index ca108e1..5828207 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -13,14 +13,15 @@ const Config = { * {Array} Array of operators weights in energy equivalent. Every value of this * array is bind to special operator run on VM. The same sequence should be * implemented. See Operators.operators getter for details. Values may be float. - * Values titles: - * [ - * onVar,onConst,onCondition,onLoop,omOperator,onLookAt,onEatLeft,onEatRight,onEatUp, - * onEatDown,onStepLeft,onStepRight,onStepUp,onStepDown,onFromMem,onToMem, - * onMyX,onMyY,onCheckLeft,onCheckRight,onCheckUp,onCheckDown - * ] */ - orgOperatorWeights: [.00001,.00001,.00001,.0000001,.00001,.000001,.0002,.0002,.0002,.0002,.0002,.0002,.0002,.0002,.00001,.00001,.00001,.00001,.00001,.00001,.00001,.00001], + orgOperatorWeights: [ + .000001, .00001, .000001, .00000001, .000001, // var, const, if, loop, operator, + .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, + .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, + .000001, .000001, // fromMem, toMem, + .000001, .000001, // myX, myY, + .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown + ], /** * {Array} Probabilities which used, when mutator decides what to do: * add, change, delete code line inside the vm; change amount of diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index da46d1c..6ea5722 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -244,7 +244,7 @@ class Organism extends Observer { } _updateClone() { - if (this._energy > OConfig.orgCloneMinEnergy && this._energy > 0) { + if (this._energy > OConfig.orgCloneMinEnergy * this.vm.size && this._energy > 0) { this.fire(CLONE, this); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index aca2f10..46d0039 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -275,8 +275,11 @@ class Organisms extends Configurable { // if (this.organisms.size >= OConfig.orgMaxOrgs && Math.random() <= ((org.energy / 10000000000000) * (org.iterations / OConfig.orgAlivePeriod))) { // this.randOrg().destroy(); // } - if (this.organisms.size < OConfig.orgMaxOrgs) { - this._clone(org); + //if (this.organisms.size >= maxOrgs && Math.random() <= org.energy / this._maxEnergy) {this.randOrg().destroy()} + //if (this.organisms.size < maxOrgs) {this._clone(org)} + if (this.organisms.size < OConfig.orgMaxOrgs && this._clone(org)) { + org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size); + this.organisms.last.val.energy -= (OConfig.orgCloneMinEnergy * this.organisms.last.val.vm.size) } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index e95639d..9f852e9 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -99,7 +99,7 @@ ClientConfig.init({ * {Number} size of one clever energy block (percent from world size). Calculates * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyBlockPercent */ - worldCleverEnergyBlockPercent: 0.00002, + worldCleverEnergyBlockPercent: 0.00001, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will @@ -112,7 +112,7 @@ ClientConfig.init({ * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.15, + worldCleverEnergyMinPercent: 0.015, /** * {Number} Zoom speed 0..1 */ From e08144de0bf3b5eada5c002253a900f3a9f58f20 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 20:37:50 +0200 Subject: [PATCH 219/291] from now color means amount of energy: green - low energy, red - hi energy fixed critical issue with grabbing extra energy from organisms during cloning --- .../src/manager/plugins/organisms/Config.js | 19 +++++--------- .../src/manager/plugins/organisms/Organism.js | 25 +++++++----------- .../manager/plugins/organisms/Organisms.js | 26 ++++++++++++------- .../plugins/organisms/dos/OrganismSpec.js | 2 -- 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5828207..81c9005 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -54,14 +54,14 @@ const Config = { * If amount of energy less then orgCloneMinEnergy * vm.size, then clone * is not possible */ - orgCloneMinEnergy: 500000, + orgCloneMinEnergy: 10000, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing * will be provided. Killing of organism will be done using random organism * selection from population */ - orgKillOnClone: false, + //orgKillOnClone: false, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -72,7 +72,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 6000, + orgRainMutationPeriod: 4000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -88,17 +88,17 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 100, + orgCrossoverPeriod: 1000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 0, + orgRandomOrgPeriod: 3000, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 20000, + orgAlivePeriod: 40000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -124,7 +124,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 500, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ @@ -135,11 +135,6 @@ const Config = { * by operator and not by evolution. */ orgStartEnergy: 10000000, - /** - * {Number} Begin color of "empty" organism. It's just an index of color. - * Starts from0 and till Number.MAX_VALUE - */ - orgStartColor: 50, /** * {Number} Amount of bits for storing a numeric constant inside byte code */ diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 6ea5722..192b839 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -11,7 +11,6 @@ const Helper = require('./../../../../../common/src/Helper'); const OConfig = require('./../../../manager/plugins/organisms/Config'); const EVENT_AMOUNT = require('./../../../share/Events').EVENT_AMOUNT; const VM = require('./../../../vm/VM'); -const Num = require('./../../../vm/Num'); const DESTROY = 0; const CLONE = 1; @@ -26,7 +25,7 @@ const ORG_EVENTS = { ITERATION }; -const MAX_COLORS = 40000; +const MAX_COLORS = 4000; class Organism extends Observer { /** @@ -38,7 +37,7 @@ class Organism extends Observer { // // Maximum possible colors for this value is MAX_COLORS // - const frequency = 0.0001; + const frequency = 0.0005; const r = Math.sin(frequency * index ) * 127 + 128; const g = Math.sin(frequency * index + 2) * 127 + 128; @@ -88,6 +87,7 @@ class Organism extends Observer { this._iterations = -1; this._changes = 0; this._item = item; + this._maxEnergy = 0; this._fnId = 0; } @@ -103,7 +103,6 @@ class Organism extends Observer { get energy() {return this._energy} get startEnergy() {return this._startEnergy} get color() {return this._color} - get colorIndex() {return this._colorIndex} get mem() {return this._mem} get posId() {return Helper.posId(this._x, this._y)} @@ -111,9 +110,10 @@ class Organism extends Observer { set y(newY) {this._y = newY} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set energy(e) {this._energy = e} + set energy(e) {this._energy = e; this._updateColor()} set startEnergy(e) {this._startEnergy = e} - set changes(c) {this._updateColor(c); this._changes = c} + set changes(c) {this._changes = c} + set maxEnergy(e) {this._maxEnergy = e} /** * Runs one code iteration (amount of lines set in Config.codeYieldPeriod) and returns @@ -151,7 +151,6 @@ class Organism extends Observer { energy : this._energy, startEnergy : this._startEnergy, color : this._color, - colorIndex : this._colorIndex, mutationProbs : this._mutationProbs, mutationPeriod : this._mutationPeriod, mutationPercent : this._mutationPercent, @@ -180,7 +179,6 @@ class Organism extends Observer { this._energy = json.energy; this._startEnergy = json.startEnergy; this._color = json.color; - this._colorIndex = json.colorIndex; this._mutationProbs = json.mutationProbs; this._mutationPeriod = json.mutationPeriod; this._mutationPercent = json.mutationPercent; @@ -216,8 +214,7 @@ class Organism extends Observer { this.vm = new VM(this, this._operatorCls, OConfig.orgOperatorWeights); this._energy = OConfig.orgStartEnergy; this._startEnergy = OConfig.orgStartEnergy; - this._colorIndex = OConfig.orgStartColor * Num.MAX_BITS; - this._color = Organism.getColor(this._colorIndex); + this._color = Organism.getColor(MAX_COLORS); this._mutationProbs = OConfig.orgMutationProbs.slice(); this._mutationPeriod = OConfig.orgRainMutationPeriod; this._mutationPercent = OConfig.orgRainMutationPercent; @@ -231,20 +228,18 @@ class Organism extends Observer { this._energy = parent.energy; this._startEnergy = parent.energy; this._color = parent.color; - this._colorIndex = parent.colorIndex; this._mutationProbs = parent.mutationProbs.slice(); this._mutationPeriod = parent.mutationPeriod; this._mutationPercent = parent.mutationPercent; this._mem = parent.mem.slice(); } - _updateColor(changes) { - this._colorIndex += (changes - this._changes); - this._color = Organism.getColor((this._colorIndex / Num.MAX_BITS + .5) << 0); + _updateColor() { + this._color = Organism.getColor((this._energy * MAX_COLORS) / this._maxEnergy); } _updateClone() { - if (this._energy > OConfig.orgCloneMinEnergy * this.vm.size && this._energy > 0) { + if ((this._energy > OConfig.orgCloneMinEnergy * this.vm.size) && this._energy > 0) { this.fire(CLONE, this); } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 46d0039..6e68995 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -73,13 +73,6 @@ class Organisms extends Configurable { */ createEmptyOrg(...args) {} - /** - * Is called at the end of run() method - * @param {Organism} org Current organism - * @abstract - */ - onOrganism(org) {} - constructor(manager) { super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); this.organisms = manager.organisms; @@ -88,6 +81,8 @@ class Organisms extends Configurable { this.world = manager.world; this._mutator = new Mutator(manager, this); + this._maxEnergy = 0; + this._oldMaxEnergy = 0; this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -111,6 +106,19 @@ class Organisms extends Configurable { super.destroy(); } + /** + * Is called at the end of run() method + * @param {Organism} org Current organism + */ + onOrganism(org) { + if (org.energy > this._oldMaxEnergy) {this._oldMaxEnergy = org.energy} + if (org === this.organisms.last.val) { + this._maxEnergy = this._oldMaxEnergy; + this._oldMaxEnergy = 0; + } + org.maxEnergy = this._maxEnergy; + } + addOrgHandlers(org) { org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); @@ -278,8 +286,8 @@ class Organisms extends Configurable { //if (this.organisms.size >= maxOrgs && Math.random() <= org.energy / this._maxEnergy) {this.randOrg().destroy()} //if (this.organisms.size < maxOrgs) {this._clone(org)} if (this.organisms.size < OConfig.orgMaxOrgs && this._clone(org)) { - org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size); - this.organisms.last.val.energy -= (OConfig.orgCloneMinEnergy * this.organisms.last.val.vm.size) + org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size / 2); + this.organisms.last.val.energy -= (OConfig.orgCloneMinEnergy * this.organisms.last.val.vm.size / 2) } } diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 672b344..a162a61 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -158,11 +158,9 @@ describe("client/src/organism/OrganismDos", () => { it("Checking if changes affects color", () => { const color = org.color; - const colorIndex = org.colorIndex; expect(org.changes).toBe(0); org.changes = 10; expect(org.color).not.toBe(color); - expect(org.colorIndex).not.toBe(colorIndex); }); }); From 92d0b61da30ad9445b84565da4aed99afb996f33 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Feb 2018 23:50:30 +0200 Subject: [PATCH 220/291] tuned default configs added amount of energy in a world (percent) to the main status line added killed organisms by other organisms to the main status --- client/src/manager/plugins/Energy.js | 1 + .../src/manager/plugins/organisms/Config.js | 10 +- client/src/manager/plugins/status/Status.js | 99 ++++++++++--------- .../manager/plugins/status/charts/Charts.js | 46 ++++----- client/src/share/Config.js | 6 +- client/src/share/Events.js | 3 +- 6 files changed, 90 insertions(+), 75 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index c8907c6..aa2af33 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -38,6 +38,7 @@ class Energy { } const energyPercent = this._getEnergyPercent(); + this._manager.fire(EVENTS.WORLD_ENERGY, energyPercent); if (energyPercent <= Config.worldCleverEnergyMinPercent) {this._cleverActive = true} else if (energyPercent >= Config.worldCleverEnergyMaxPercent) {this._cleverActive = false} diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 81c9005..3002558 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -54,7 +54,7 @@ const Config = { * If amount of energy less then orgCloneMinEnergy * vm.size, then clone * is not possible */ - orgCloneMinEnergy: 10000, + orgCloneMinEnergy: 100000, /** * {Boolean} true means, that one organism will be killed just after new * organism has cloned. If population is less then orgMaxOrgs, then no killing @@ -88,12 +88,12 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 1000, + orgCrossoverPeriod: 4000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 3000, + orgRandomOrgPeriod: 8000, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever @@ -124,11 +124,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 3000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 500, + orgStartAmount: 3000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index ebae981..dc183a1 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -37,38 +37,40 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, changes:0, fit :0, age:0, code:0, + lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, wenergy:0, changes:0, fit :0, age:0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killclone:0 }; - this._stamp = 0; - this._ips = 0; - this._ipsTimes = 0; - this._energy = 0; - this._pickEnergy = 0; - this._eatEnergy = 0; - this._fitness = 0; - this._changes = 0; - this._codeSize = 0; - this._codeRuns = 0; - this._age = 0; - this._ageCount = 0; - this._times = 0; - this._kill = new Array(9); - this._statusCfg = statCfg; - this._firstCall = true; - - this._onLoopCb = this._onLoop.bind(this); - this._onIpsCb = this._onIps.bind(this); - this._onEatEnergyCb = this._onEatEnergy.bind(this); - this._onKillOrgCb = this._onKillOrg.bind(this); - this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); - this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); - this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 3); - this._onKillEatCb = this._onKillHandlerOrg.bind(this, 4); - this._onKillOverCb = this._onKillHandlerOrg.bind(this, 5); - this._onKillOutCb = this._onKillHandlerOrg.bind(this, 6); - this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); - this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); + this._stamp = 0; + this._ips = 0; + this._ipsTimes = 0; + this._energy = 0; + this._pickEnergy = 0; + this._eatEnergy = 0; + this._fitness = 0; + this._changes = 0; + this._codeSize = 0; + this._codeRuns = 0; + this._age = 0; + this._ageCount = 0; + this._times = 0; + this._kill = new Array(9); + this._energyPercent = 0.0; + this._statusCfg = statCfg; + this._firstCall = true; + + this._onLoopCb = this._onLoop.bind(this); + this._onIpsCb = this._onIps.bind(this); + this._onEatEnergyCb = this._onEatEnergy.bind(this); + this._onKillOrgCb = this._onKillOrg.bind(this); + this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); + this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); + this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 3); + this._onKillEatCb = this._onKillHandlerOrg.bind(this, 4); + this._onKillOverCb = this._onKillHandlerOrg.bind(this, 5); + this._onKillOutCb = this._onKillHandlerOrg.bind(this, 6); + this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); + this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); + this._onWorldEnergyCb = this._onWorldEnergy.bind(this); Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.IPS, this._onIpsCb); @@ -82,6 +84,7 @@ class Status extends Configurable { manager.on(EVENTS.KILL_STEP_OUT, this._onKillOutCb); manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); + manager.on(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); _fill(this._kill, 0); } @@ -89,6 +92,7 @@ class Status extends Configurable { destroy() { const man = this.parent; + man.off(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); man.off(EVENTS.KILL_STEP_OUT, this._onKillOutCb); @@ -102,20 +106,21 @@ class Status extends Configurable { man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(man, 'onLoop', this._onLoopCb); - this._onKillOrgCb = null; - this._onKillTourCb = null; - this._onEatEnergyCb = null; - this._onKillCloneCb = null; - this._onKillInCb = null; - this._onKillOutCb = null; - this._onKillOverCb = null; - this._onKillEatCb = null; - this._onKillAgeCb = null; - this._onKillEnergyCb = null; - this._onIpsCb = null; - this._onLoopCb = null; - this._status = null; - this._statusCfg = null; + this._onWorldEnergyCb = null; + this._onKillOrgCb = null; + this._onKillTourCb = null; + this._onEatEnergyCb = null; + this._onKillCloneCb = null; + this._onKillInCb = null; + this._onKillOutCb = null; + this._onKillOverCb = null; + this._onKillEatCb = null; + this._onKillAgeCb = null; + this._onKillEnergyCb = null; + this._onIpsCb = null; + this._onLoopCb = null; + this._status = null; + this._statusCfg = null; } _onBeforeLoop(orgs) { @@ -179,6 +184,8 @@ class Status extends Configurable { status.killin = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); + status.wenergy = fix(this._energyPercent, 2); + !this._firstCall && this.onStatus(status, orgs.size); this._onAfterLoop(stamp); this._firstCall = false; @@ -220,6 +227,10 @@ class Status extends Configurable { _onKillHandlerOrg(index) { this._kill[index]++; } + + _onWorldEnergy(percent) { + this._energyPercent = percent; + } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 824506d..46d0de5 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -76,6 +76,27 @@ const PRESETS = { }; class Charts extends Status { + static _to12h(time) { + let hours = time.getHours(); + let minutes = time.getMinutes(); + + hours = hours % 12; + hours = hours ? hours : 12; + + return hours + ':' + minutes; + } + + static _createHeader() { + return document.body.appendChild(Helper.setStyles('DIV', { + position : 'absolute', + top : '7px', + left : '35px', + color : '#fff', + fontSize : '18px', + fontFamily: 'Consolas' + })); + } + constructor(manager) { super(manager, Config, API); const periodSec = Config.period / 1000; @@ -143,33 +164,14 @@ class Charts extends Status { const conns = `${active[0] ? '^' : ''}${active[1] ? '>' : ''}${active[2] ? 'v' : ''}${active[3] ? '<' : ''}`; const ips = `ips:${status.ips}`; const enrg = `enrg:${status.eenergy}`; + const wnrg = `wnrg:${status.wenergy}`; const code = `cod:${status.code}`; const age = `age:${status.age}`; const kill = `kil:${status.kill}`; + const kilo = `kilo:${status.killeat}`; const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${enrg} ${code} ${age} ${kill} ${orgs}`; - } - - _to12h(time) { - let hours = time.getHours(); - let minutes = time.getMinutes(); - - hours = hours % 12; - hours = hours ? hours : 12; - - return hours + ':' + minutes; - } - - _createHeader() { - return document.body.appendChild(Helper.setStyles('DIV', { - position : 'absolute', - top : '7px', - left : '35px', - color : '#fff', - fontSize : '18px', - fontFamily: 'Consolas' - })); + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; } /** diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 9f852e9..f3d4e38 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -73,7 +73,7 @@ ClientConfig.init({ * Should be less then 100.0 and more and equal to 0.0. 0.17 is a * normal percent for this system. */ - worldEnergyCheckPercent: 0.001, + worldEnergyCheckPercent: 0.0005, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckPercent. May be 0 if @@ -106,13 +106,13 @@ ClientConfig.init({ * be less then worldCleverEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMaxPercent: 0.03, + worldCleverEnergyMaxPercent: 0.04, /** * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.015, + worldCleverEnergyMinPercent: 0.001, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/share/Events.js b/client/src/share/Events.js index a2c7a7b..2c8bb90 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -36,7 +36,8 @@ const EVENTS = { RUN : 26, STOP : 27, RESET_CODE : 28, - CHECK_AT : 29 + CHECK_AT : 29, + WORLD_ENERGY : 30 }; const EVENT_AMOUNT = Object.keys(EVENTS).length; From 268a5895ba886f6b258ea0d45c4f5a356039799e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Feb 2018 00:09:00 +0200 Subject: [PATCH 221/291] fixed an issue with world energy percent --- client/src/manager/plugins/organisms/Config.js | 2 +- client/src/manager/plugins/status/Status.js | 2 +- client/src/manager/plugins/status/charts/Charts.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 3002558..0391568 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -124,7 +124,7 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 3000, + orgMaxOrgs: 2000, /** * {Number} Amount of organisms we have to create on program start */ diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index dc183a1..3bca1dd 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -184,7 +184,7 @@ class Status extends Configurable { status.killin = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); - status.wenergy = fix(this._energyPercent, 2); + status.wenergy = fix(this._energyPercent, 4); !this._firstCall && this.onStatus(status, orgs.size); this._onAfterLoop(stamp); diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 46d0de5..c2f77ac 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -102,7 +102,7 @@ class Charts extends Status { const periodSec = Config.period / 1000; this._data = new Array(2); - this._headerEl = this._createHeader(); + this._headerEl = Charts._createHeader(); this._charts = { lps : new Chart('LPS - Lines Per Second', Config.charts.lps), ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), @@ -149,7 +149,7 @@ class Charts extends Status { _updateCharts(status) { const data = this._data; const charts = this._charts; - data[0] = this._to12h(new Date); + data[0] = Charts._to12h(new Date); _each(charts, (chart, key) => { data[1] = status[key]; From 52a5d18ae6c37dac89e91033201ab01503b2fd20 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Feb 2018 00:31:17 +0200 Subject: [PATCH 222/291] added wenergy to Console plugin --- client/src/manager/plugins/status/console/Console.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index cfe5a14..cc259f0 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -50,6 +50,7 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 19); const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); + const wenergy = format(status.wenergy, 'wnrg', 11); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); @@ -57,7 +58,7 @@ class Console extends Status { const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${wenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); } } From 2b3cca358563950b0b1a5620b31b04a9beaca58b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Feb 2018 12:22:37 +0200 Subject: [PATCH 223/291] changed range of low energy period --- client/src/share/Config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/share/Config.js b/client/src/share/Config.js index f3d4e38..58e704f 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -112,7 +112,7 @@ ClientConfig.init({ * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.001, + worldCleverEnergyMinPercent: 0.0005, /** * {Number} Zoom speed 0..1 */ From 0cdad1fba3230837c9119345dae6adf76bf603d2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Feb 2018 15:42:21 +0200 Subject: [PATCH 224/291] changed logic of energy calculation. from now real amount of energy in a world is calculating. so, instead of % you have to set amount of energy --- client/src/manager/plugins/Energy.js | 23 +++++++++-------- .../src/manager/plugins/organisms/Config.js | 4 +-- client/src/manager/plugins/status/Status.js | 6 ++--- .../manager/plugins/status/charts/Charts.js | 2 +- .../manager/plugins/status/console/Console.js | 2 +- client/src/share/Config.js | 25 ++++++++----------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index aa2af33..504f422 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -9,13 +9,15 @@ const Organism = require('./../../manager/plugins/organisms/Organism').Organism; const Console = require('./../../share/Console'); const EVENTS = require('./../../share/Events').EVENTS; +const POSID = Helper.posId; + class Energy { constructor(manager) { this._manager = manager; this._lastX = -1; this._lastY = -1; this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyBlockPercent; + this._amount = Config.worldCleverEnergyBlockSize; this._cleverActive = true; this._onIterationCb = this._onIteration.bind(this); @@ -37,12 +39,12 @@ class Energy { return; } - const energyPercent = this._getEnergyPercent(); - this._manager.fire(EVENTS.WORLD_ENERGY, energyPercent); - if (energyPercent <= Config.worldCleverEnergyMinPercent) {this._cleverActive = true} - else if (energyPercent >= Config.worldCleverEnergyMaxPercent) {this._cleverActive = false} + const energy = this._getWorldEnergy(); + this._manager.fire(EVENTS.WORLD_ENERGY, energy); + if (energy <= Config.worldCleverEnergyMin) {this._cleverActive = true} + else if (energy >= Config.worldCleverEnergyMax) {this._cleverActive = false} - if (energyPercent <= Config.worldEnergyCheckPercent) { + if (energy <= Config.worldEnergyCheckAmount) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); } } @@ -73,7 +75,7 @@ class Energy { if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._amount < 0) { this._lastX = this._lastY = -1; this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldWidth * Config.worldHeight * Config.worldCleverEnergyBlockPercent; + this._amount = Config.worldCleverEnergyBlockSize; return; } @@ -83,19 +85,20 @@ class Energy { if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex))} } - _getEnergyPercent() { + _getWorldEnergy() { let energy = 0; const world = this._manager.world; const width = Config.worldWidth; const height = Config.worldHeight; + const man = this._manager; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - if (world.getDot(x, y) > 0) {energy++} + if (typeof man.organisms[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} } } - return energy / (width * height); + return energy; } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 0391568..a7b14d4 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -124,11 +124,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 2000, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 3000, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 3bca1dd..db9cb19 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -54,7 +54,7 @@ class Status extends Configurable { this._ageCount = 0; this._times = 0; this._kill = new Array(9); - this._energyPercent = 0.0; + this._worldEnergy = 0.0; this._statusCfg = statCfg; this._firstCall = true; @@ -184,7 +184,7 @@ class Status extends Configurable { status.killin = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); - status.wenergy = fix(this._energyPercent, 4); + status.wenergy = fix(this._worldEnergy / (Config.worldWidth * Config.worldHeight * 0xffffff), 4); !this._firstCall && this.onStatus(status, orgs.size); this._onAfterLoop(stamp); @@ -229,7 +229,7 @@ class Status extends Configurable { } _onWorldEnergy(percent) { - this._energyPercent = percent; + this._worldEnergy = percent; } } diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index c2f77ac..a646888 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -171,7 +171,7 @@ class Charts extends Status { const kilo = `kilo:${status.killeat}`; const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg}% ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; } /** diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index cc259f0..61ec737 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -50,7 +50,7 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 19); const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); - const wenergy = format(status.wenergy, 'wnrg', 11); + const wenergy = format(status.wenergy, 'wnrg', 12); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 58e704f..3d31589 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -67,16 +67,14 @@ ClientConfig.init({ */ worldCyclical: false, /** - * {Number} Minimum percent of energy in current world. Under percent i mean - * percent from entire world area (100%). If the energy will be less - * or equal then this percent, then new random energy should be added. - * Should be less then 100.0 and more and equal to 0.0. 0.17 is a - * normal percent for this system. + * {Number} Minimum amount of energy in current world. Under amount i mean + * sum from entire world area (100%). If the energy will be less + * or equal then this value, then new random energy should be added. */ - worldEnergyCheckPercent: 0.0005, + worldEnergyCheckAmount: 10000000, /** * {Number} An amount of iteration, after which we have to check world energy - * amount. Works in pair with worldEnergyCheckPercent. May be 0 if + * amount. Works in pair with worldEnergyCheckAmount. May be 0 if * you want to disable it */ worldEnergyCheckPeriod: 5000, @@ -96,23 +94,22 @@ ClientConfig.init({ */ worldCleverEnergy: true, /** - * {Number} size of one clever energy block (percent from world size). Calculates - * in this way amountOfDotsInBlock = worldWidth * worldHeight * worldCleverEnergyBlockPercent + * {Number} size of one clever energy block in dots. */ - worldCleverEnergyBlockPercent: 0.00001, + worldCleverEnergyBlockSize: 400, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will - * be less then worldCleverEnergyMinPercent. These two configs create cyclical + * be less then worldCleverEnergyMin. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMaxPercent: 0.04, + worldCleverEnergyMax: 9123953878473, /** - * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from + * {Number} Opposite to worldCleverEnergyMax. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: 0.0005, + worldCleverEnergyMin: 91239538784, /** * {Number} Zoom speed 0..1 */ From 397d17561424c78e7d54fdcf6495de64f6e5625e Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Feb 2018 23:59:12 +0200 Subject: [PATCH 225/291] finally! i found a solution for compete organisms logic: in one world organism will compete for energy and ability to clone them added arrows (up/down) to show user if energy is increasing (summer) or decreasing (winter) in a world clever energy min/max configs changed to percent values increased speed of energy adding in a world during increase period (summer) --- client/src/manager/plugins/Energy.js | 20 +-- .../src/manager/plugins/organisms/Organism.js | 2 +- .../manager/plugins/organisms/Organisms.js | 14 +- .../plugins/organisms/dos/Organisms.js | 23 +++- client/src/manager/plugins/status/Status.js | 120 ++++++++++-------- .../manager/plugins/status/charts/Charts.js | 3 +- .../manager/plugins/status/console/Console.js | 2 +- client/src/share/Config.js | 17 +-- client/src/share/Events.js | 4 +- client/src/view/World.js | 1 - 10 files changed, 123 insertions(+), 83 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 504f422..2025460 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -41,8 +41,8 @@ class Energy { const energy = this._getWorldEnergy(); this._manager.fire(EVENTS.WORLD_ENERGY, energy); - if (energy <= Config.worldCleverEnergyMin) {this._cleverActive = true} - else if (energy >= Config.worldCleverEnergyMax) {this._cleverActive = false} + if (energy <= Config.worldCleverEnergyMinPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = true)} + else if (energy >= Config.worldCleverEnergyMaxPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = false)} if (energy <= Config.worldEnergyCheckAmount) { this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); @@ -80,9 +80,13 @@ class Energy { } const world = this._manager.world; - this._lastX = x + Helper.rand(3) - 1; - this._lastY = y + Helper.rand(3) - 1; - if (world.getDot(this._lastX, this._lastY) === 0) {world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex))} + for (let i = 0; i < 8; i++) { + this._lastX = x + Helper.rand(3) - 1; + this._lastY = y + Helper.rand(3) - 1; + if (world.getDot(this._lastX, this._lastY) === 0) { + world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex)) + } + } } _getWorldEnergy() { @@ -90,15 +94,15 @@ class Energy { const world = this._manager.world; const width = Config.worldWidth; const height = Config.worldHeight; - const man = this._manager; + const orgs = this._manager.organisms; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - if (typeof man.organisms[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} + if (typeof orgs[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} } } - return energy; + return energy / (width * height * 0xffffffff); } } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 192b839..70d1ea5 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -110,7 +110,7 @@ class Organism extends Observer { set y(newY) {this._y = newY} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set energy(e) {this._energy = e; this._updateColor()} + set energy(e) {if (this.vm !== null) { this._energy = e; this._updateColor()}} set startEnergy(e) {this._startEnergy = e} set changes(c) {this._changes = c} set maxEnergy(e) {this._maxEnergy = e} diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 6e68995..04d004a 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -275,7 +275,7 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - //const maxOrgs = OConfig.orgMaxOrgs; + const maxOrgs = OConfig.orgMaxOrgs; //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} @@ -283,9 +283,17 @@ class Organisms extends Configurable { // if (this.organisms.size >= OConfig.orgMaxOrgs && Math.random() <= ((org.energy / 10000000000000) * (org.iterations / OConfig.orgAlivePeriod))) { // this.randOrg().destroy(); // } - //if (this.organisms.size >= maxOrgs && Math.random() <= org.energy / this._maxEnergy) {this.randOrg().destroy()} //if (this.organisms.size < maxOrgs) {this._clone(org)} - if (this.organisms.size < OConfig.orgMaxOrgs && this._clone(org)) { + //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this.randOrg().destroy()} + // + // This is very important part of application! Cloning should be available only if + // amount of organisms is less then maximum or if current organism ate other right + // now (and free one slot in Organisms.organisms queue). It's not a good idea to + // kill organisms with small amount of energy or support more more energetic + // organisms before cloning. They should kill each other to have a possibility + // of cloning. + // + if (this.organisms.size < maxOrgs && this._clone(org)) { org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size / 2); this.organisms.last.val.energy -= (OConfig.orgCloneMinEnergy * this.organisms.last.val.vm.size / 2) } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index bb15aca..f4b50be 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -164,21 +164,36 @@ class Organisms extends BaseOrganisms { const eat = ret.ret; [x, y] = NORMALIZE_NO_DIR(x, y); const posId = POSID(x, y); - + // + // Energy found + // if (typeof(positions[posId]) === 'undefined') { if (eat > 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); } else { ret.ret = eat; - this.world.setDot(x, y, ((-eat + .5) << 0) + this.world.getDot(x, y)); + this.world.setDot(x, y, (((-eat + .5) << 0) >>> 0) + this.world.getDot(x, y)); this.parent.fire(EVENTS.EAT_ENERGY, eat); } + // + // Organism found + // } else { const victimOrg = positions[posId]; ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); - victimOrg.energy <= ret.ret && this.parent.fire(EVENTS.KILL_EAT, victimOrg); - victimOrg.energy -= ret.ret; + if (victimOrg.energy <= ret.ret) { + this.parent.fire(EVENTS.KILL_EAT, victimOrg); + // + // IMPORTANT: + // We have to do destroy here, to have a possibility for current + // (winner) organism to clone himself after eating other organism. + // This is how organisms compete for an ability to clone + // + victimOrg.destroy(); + } else { + victimOrg.energy -= ret.ret; + } } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index db9cb19..a24a2a9 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -37,7 +37,7 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, wenergy:0, changes:0, fit :0, age:0, code:0, + lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, wenergy:0, wenergyup:true, changes:0, fit:0, age:0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killclone:0 }; this._stamp = 0; @@ -54,37 +54,40 @@ class Status extends Configurable { this._ageCount = 0; this._times = 0; this._kill = new Array(9); - this._worldEnergy = 0.0; + this._worldEnergy = 0.0; + this._worldEnergyUp = true; this._statusCfg = statCfg; this._firstCall = true; - this._onLoopCb = this._onLoop.bind(this); - this._onIpsCb = this._onIps.bind(this); - this._onEatEnergyCb = this._onEatEnergy.bind(this); - this._onKillOrgCb = this._onKillOrg.bind(this); - this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); - this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); - this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 3); - this._onKillEatCb = this._onKillHandlerOrg.bind(this, 4); - this._onKillOverCb = this._onKillHandlerOrg.bind(this, 5); - this._onKillOutCb = this._onKillHandlerOrg.bind(this, 6); - this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); - this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); - this._onWorldEnergyCb = this._onWorldEnergy.bind(this); + this._onLoopCb = this._onLoop.bind(this); + this._onIpsCb = this._onIps.bind(this); + this._onEatEnergyCb = this._onEatEnergy.bind(this); + this._onKillOrgCb = this._onKillOrg.bind(this); + this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); + this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); + this._onKillAgeCb = this._onKillHandlerOrg.bind(this, 3); + this._onKillEatCb = this._onKillHandlerOrg.bind(this, 4); + this._onKillOverCb = this._onKillHandlerOrg.bind(this, 5); + this._onKillOutCb = this._onKillHandlerOrg.bind(this, 6); + this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); + this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); + this._onWorldEnergyCb = this._onWorldEnergy.bind(this); + this._onWorldEnergyUpCb = this._onWorldEnergyUp.bind(this); Helper.override(manager, 'onLoop', this._onLoopCb); - manager.on(EVENTS.IPS, this._onIpsCb); - manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); - manager.on(EVENTS.KILL, this._onKillOrgCb); - manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); - manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); - manager.on(EVENTS.KILL_AGE, this._onKillAgeCb); - manager.on(EVENTS.KILL_EAT, this._onKillEatCb); - manager.on(EVENTS.KILL_OVERFLOW, this._onKillOverCb); - manager.on(EVENTS.KILL_STEP_OUT, this._onKillOutCb); - manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); - manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); - manager.on(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); + manager.on(EVENTS.IPS, this._onIpsCb); + manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + manager.on(EVENTS.KILL, this._onKillOrgCb); + manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); + manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); + manager.on(EVENTS.KILL_AGE, this._onKillAgeCb); + manager.on(EVENTS.KILL_EAT, this._onKillEatCb); + manager.on(EVENTS.KILL_OVERFLOW, this._onKillOverCb); + manager.on(EVENTS.KILL_STEP_OUT, this._onKillOutCb); + manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); + manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); + manager.on(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); + manager.on(EVENTS.WORLD_ENERGY_UP, this._onWorldEnergyUpCb); _fill(this._kill, 0); } @@ -92,35 +95,37 @@ class Status extends Configurable { destroy() { const man = this.parent; - man.off(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); - man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); - man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); - man.off(EVENTS.KILL_STEP_OUT, this._onKillOutCb); - man.off(EVENTS.KILL_OVERFLOW, this._onKillOverCb); - man.off(EVENTS.KILL_EAT, this._onKillEatCb); - man.off(EVENTS.KILL_AGE, this._onKillAgeCb); - man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); - man.off(EVENTS.KILL_TOUR, this._onKillTourCb); - man.off(EVENTS.KILL, this._onKillOrgCb); - man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); - man.off(EVENTS.IPS, this._onIpsCb); + man.off(EVENTS.WORLD_ENERGY_UP, this._onWorldEnergyUpCb); + man.off(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); + man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); + man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); + man.off(EVENTS.KILL_STEP_OUT, this._onKillOutCb); + man.off(EVENTS.KILL_OVERFLOW, this._onKillOverCb); + man.off(EVENTS.KILL_EAT, this._onKillEatCb); + man.off(EVENTS.KILL_AGE, this._onKillAgeCb); + man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); + man.off(EVENTS.KILL_TOUR, this._onKillTourCb); + man.off(EVENTS.KILL, this._onKillOrgCb); + man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(man, 'onLoop', this._onLoopCb); - this._onWorldEnergyCb = null; - this._onKillOrgCb = null; - this._onKillTourCb = null; - this._onEatEnergyCb = null; - this._onKillCloneCb = null; - this._onKillInCb = null; - this._onKillOutCb = null; - this._onKillOverCb = null; - this._onKillEatCb = null; - this._onKillAgeCb = null; - this._onKillEnergyCb = null; - this._onIpsCb = null; - this._onLoopCb = null; - this._status = null; - this._statusCfg = null; + this._onWorldEnergyUpCb = null; + this._onWorldEnergyCb = null; + this._onKillOrgCb = null; + this._onKillTourCb = null; + this._onEatEnergyCb = null; + this._onKillCloneCb = null; + this._onKillInCb = null; + this._onKillOutCb = null; + this._onKillOverCb = null; + this._onKillEatCb = null; + this._onKillAgeCb = null; + this._onKillEnergyCb = null; + this._onIpsCb = null; + this._onLoopCb = null; + this._status = null; + this._statusCfg = null; } _onBeforeLoop(orgs) { @@ -184,7 +189,8 @@ class Status extends Configurable { status.killin = fix(this._kill[7], 2); status.killclone = fix(this._kill[8], 2); - status.wenergy = fix(this._worldEnergy / (Config.worldWidth * Config.worldHeight * 0xffffff), 4); + status.wenergy = fix(this._worldEnergy, 5); + status.wenergyup = this._worldEnergyUp; !this._firstCall && this.onStatus(status, orgs.size); this._onAfterLoop(stamp); @@ -231,6 +237,10 @@ class Status extends Configurable { _onWorldEnergy(percent) { this._worldEnergy = percent; } + + _onWorldEnergyUp(up) { + this._worldEnergyUp = up; + } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index a646888..24fa213 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -165,13 +165,14 @@ class Charts extends Status { const ips = `ips:${status.ips}`; const enrg = `enrg:${status.eenergy}`; const wnrg = `wnrg:${status.wenergy}`; + const wnrgup = status.wenergyup ? '\u2191' : '\u2193'; const code = `cod:${status.code}`; const age = `age:${status.age}`; const kill = `kil:${status.kill}`; const kilo = `kilo:${status.killeat}`; const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg}% ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${wnrgup} ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; } /** diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 61ec737..37aef97 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -50,7 +50,7 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 19); const spenergy = format(status.penergy, 'pnrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); - const wenergy = format(status.wenergy, 'wnrg', 12); + const wenergy = format(status.wenergy + (status.wenergyup ? '\u2191' : '\u2193'), 'wnrg', 14); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sfit = format(status.fit, 'fit', 13); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 3d31589..6dd4228 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -67,11 +67,12 @@ ClientConfig.init({ */ worldCyclical: false, /** - * {Number} Minimum amount of energy in current world. Under amount i mean - * sum from entire world area (100%). If the energy will be less - * or equal then this value, then new random energy should be added. + * {Number} Minimum percent of energy in current world. Under percent i mean + * percent from possible world fulfilled by energy with value 0xffffffff. If + * the energy will be less or equal then this value, then new random energy + * should be added. */ - worldEnergyCheckAmount: 10000000, + worldEnergyCheckAmount: .0001, /** * {Number} An amount of iteration, after which we have to check world energy * amount. Works in pair with worldEnergyCheckAmount. May be 0 if @@ -100,16 +101,16 @@ ClientConfig.init({ /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will - * be less then worldCleverEnergyMin. These two configs create cyclical + * be less then worldCleverEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMax: 9123953878473, + worldCleverEnergyMaxPercent: .0008, /** - * {Number} Opposite to worldCleverEnergyMax. Sets minimum percent from + * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMin: 91239538784, + worldCleverEnergyMinPercent: .00008, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 2c8bb90..de24460 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -37,7 +37,9 @@ const EVENTS = { STOP : 27, RESET_CODE : 28, CHECK_AT : 29, - WORLD_ENERGY : 30 + WORLD_ENERGY : 30, + WORLD_ENERGY_UP : 31 + }; const EVENT_AMOUNT = Object.keys(EVENTS).length; diff --git a/client/src/view/World.js b/client/src/view/World.js index ee77ca2..205e6f9 100644 --- a/client/src/view/World.js +++ b/client/src/view/World.js @@ -19,7 +19,6 @@ */ const Observer = require('./../../../common/src/Observer'); const Helper = require('./../../../common/src/Helper'); -const EVENTS = require('./../../src/share/Events').EVENTS; const EVENT_AMOUNT = require('./../../src/share/Events').EVENT_AMOUNT; const DOT = 0; From 6ef04544cebf8a23f47dfb3f9b6768b230c87fef Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 11:44:57 +0200 Subject: [PATCH 226/291] added new type of energy puenergy - it's amount of put energy to the world by organisms added chart for puenergy changed speed of adding clever energy --- client/src/manager/plugins/Energy.js | 36 ++++++++----------- .../manager/plugins/organisms/Organisms.js | 6 ++-- .../plugins/organisms/dos/Organisms.js | 2 +- client/src/manager/plugins/status/Status.js | 14 ++++++++ .../manager/plugins/status/charts/Charts.js | 1 + .../manager/plugins/status/charts/Config.js | 27 +++++++------- client/src/share/Events.js | 25 ++++++------- 7 files changed, 61 insertions(+), 50 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 2025460..97ae802 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -14,10 +14,6 @@ const POSID = Helper.posId; class Energy { constructor(manager) { this._manager = manager; - this._lastX = -1; - this._lastY = -1; - this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldCleverEnergyBlockSize; this._cleverActive = true; this._onIterationCb = this._onIteration.bind(this); @@ -31,7 +27,7 @@ class Energy { } _onIteration(counter) { - Config.worldCleverEnergy && this._cleverActive && this._updateCleverEnergy(); + Config.worldCleverEnergy && this._cleverActive && this._addCleverBlock(); if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { @@ -68,23 +64,21 @@ class Energy { this._manager.fire(EVENTS.UPDATE_ENERGY); } - _updateCleverEnergy() { - const x = this._lastX >= 0 ? this._lastX : Helper.rand(Config.worldWidth); - const y = this._lastY >= 0 ? this._lastY : Helper.rand(Config.worldHeight); - - if (x < 0 || x >= Config.worldWidth || y < 0 || y >= Config.worldHeight || --this._amount < 0) { - this._lastX = this._lastY = -1; - this._colorIndex = Helper.rand(Organism.getMaxColors()); - this._amount = Config.worldCleverEnergyBlockSize; - return; - } - + _addCleverBlock() { + const width = Config.worldWidth; + const height = Config.worldHeight; + const color = Helper.rand(Organism.getMaxColors()); + let block = Config.worldCleverEnergyBlockSize; const world = this._manager.world; - for (let i = 0; i < 8; i++) { - this._lastX = x + Helper.rand(3) - 1; - this._lastY = y + Helper.rand(3) - 1; - if (world.getDot(this._lastX, this._lastY) === 0) { - world.setDot(this._lastX, this._lastY, Organism.getColor(this._colorIndex)) + let x = Helper.rand(width); + let y = Helper.rand(height); + + for (let i = 0; i < block; i++) { + x = x + Helper.rand(3) - 1; + y = y + Helper.rand(3) - 1; + if (x < 0 || x >= width || y < 0 || y >= height || --block < 0) {return} + if (world.getDot(x, y) === 0) { + world.setDot(x, y, Organism.getColor(color)); } } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 04d004a..a0235e2 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -287,11 +287,11 @@ class Organisms extends Configurable { //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this.randOrg().destroy()} // // This is very important part of application! Cloning should be available only if - // amount of organisms is less then maximum or if current organism ate other right + // amount of organisms is less then maximum or if current organism has ate other just // now (and free one slot in Organisms.organisms queue). It's not a good idea to - // kill organisms with small amount of energy or support more more energetic + // kill organisms here with small amount of energy or support more energetic // organisms before cloning. They should kill each other to have a possibility - // of cloning. + // to clone them. // if (this.organisms.size < maxOrgs && this._clone(org)) { org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size / 2); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index f4b50be..7363600 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -174,7 +174,7 @@ class Organisms extends BaseOrganisms { } else { ret.ret = eat; this.world.setDot(x, y, (((-eat + .5) << 0) >>> 0) + this.world.getDot(x, y)); - this.parent.fire(EVENTS.EAT_ENERGY, eat); + this.parent.fire(EVENTS.PUT_ENERGY, eat); } // // Organism found diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index a24a2a9..ec58c8e 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -46,6 +46,7 @@ class Status extends Configurable { this._energy = 0; this._pickEnergy = 0; this._eatEnergy = 0; + this._putEnergy = 0; this._fitness = 0; this._changes = 0; this._codeSize = 0; @@ -62,6 +63,7 @@ class Status extends Configurable { this._onLoopCb = this._onLoop.bind(this); this._onIpsCb = this._onIps.bind(this); this._onEatEnergyCb = this._onEatEnergy.bind(this); + this._onPutEnergyCb = this._onPutEnergy.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); this._onKillTourCb = this._onKillHandlerOrg.bind(this, 2); @@ -77,6 +79,7 @@ class Status extends Configurable { Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + manager.on(EVENTS.PUT_ENERGY, this._onPutEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); manager.on(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); @@ -106,6 +109,7 @@ class Status extends Configurable { man.off(EVENTS.KILL_NO_ENERGY, this._onKillEnergyCb); man.off(EVENTS.KILL_TOUR, this._onKillTourCb); man.off(EVENTS.KILL, this._onKillOrgCb); + man.off(EVENTS.PUT_ENERGY, this._onPutEnergyCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(man, 'onLoop', this._onLoopCb); @@ -114,6 +118,7 @@ class Status extends Configurable { this._onWorldEnergyCb = null; this._onKillOrgCb = null; this._onKillTourCb = null; + this._onPutEnergyCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; this._onKillInCb = null; @@ -174,6 +179,7 @@ class Status extends Configurable { status.energy = fix(this._energy, 2); status.penergy = fix(this._pickEnergy * 1000, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); + status.puenergy = fix(this._putEnergy / orgAmount, 2); status.changes = +(this._changes).toFixed(1); status.fit = fix(this._fitness / 100, 2); status.age = fix(this._age / (this._ageCount || 1), 2); @@ -223,6 +229,14 @@ class Status extends Configurable { this._eatEnergy += eat; } + /** + * Calculates putting of energy by organisms to the world + * @param {Number} put Amount of put energy + */ + _onPutEnergy(put) { + this._putEnergy += put; + } + _onKillOrg(org) { if (!this._statusCfg.active) {return} this._age += org.iterations; diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 24fa213..b02b51d 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -110,6 +110,7 @@ class Charts extends Status { energy : new Chart('Average organism energy', Config.charts.energy), penergy : new Chart('Average organism\'s picked energy (all)', Config.charts.penergy), eenergy : new Chart('Average organism\'s picked energy (energy only)', Config.charts.eenergy), + puenergy : new Chart('Average organism\'s put energy to the world', Config.charts.puenergy), changes : new Chart('Average organism\'s changes (Mutations)', Config.charts.changes), fit : new Chart('Average organism\'s Fitness', Config.charts.fit), age : new Chart('Average organism\'s Age', Config.charts.age), diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 65a3a96..3facf59 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -27,19 +27,20 @@ const Config = { orgs : {pos: '0-0|16', active: false, transparent: 0.8}, penergy : {pos: '0-1|16', active: false, transparent: 0.8}, eenergy : {pos: '0-2|16', active: false, transparent: 0.8}, - fit : {pos: '0-3|16', active: false, transparent: 0.8}, - age : {pos: '1-0|16', active: false, transparent: 0.8}, - code : {pos: '1-1|16', active: false, transparent: 0.8}, - kill : {pos: '1-2|16', active: false, transparent: 0.8}, - killtour : {pos: '1-3|16', active: false, transparent: 0.8}, - killenergy: {pos: '2-0|16', active: false, transparent: 0.8}, - killage : {pos: '2-1|16', active: false, transparent: 0.8}, - killeat : {pos: '2-2|16', active: false, transparent: 0.8}, - killover : {pos: '2-3|16', active: false, transparent: 0.8}, - changes : {pos: '3-0|16', active: false, transparent: 0.8}, - killin : {pos: '3-1|16', active: false, transparent: 0.8}, - killclone : {pos: '3-2|16', active: false, transparent: 0.8}, - ips : {pos: '3-3|16', active: false, transparent: 0.8} + puenergy : {pos: '0-3|16', active: false, transparent: 0.8}, + fit : {pos: '1-0|16', active: false, transparent: 0.8}, + age : {pos: '1-1|16', active: false, transparent: 0.8}, + code : {pos: '1-2|16', active: false, transparent: 0.8}, + kill : {pos: '1-3|16', active: false, transparent: 0.8}, + killtour : {pos: '2-0|16', active: false, transparent: 0.8}, + killenergy: {pos: '2-1|16', active: false, transparent: 0.8}, + killage : {pos: '2-2|16', active: false, transparent: 0.8}, + killeat : {pos: '2-3|16', active: false, transparent: 0.8}, + killover : {pos: '3-0|16', active: false, transparent: 0.8}, + changes : {pos: '3-1|16', active: false, transparent: 0.8}, + killin : {pos: '3-2|16', active: false, transparent: 0.8}, + killclone : {pos: '3-3|16', active: false, transparent: 0.8}, + ips : {pos: 'downright', active: false, transparent: 0.8} } }; diff --git a/client/src/share/Events.js b/client/src/share/Events.js index de24460..9f8c421 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -27,18 +27,19 @@ const EVENTS = { EAT : 17, EAT_ORG : 18, EAT_ENERGY : 19, - STEP : 20, - STEP_OUT : 21, - STEP_IN : 22, - BORN_ORGANISM : 23, - GET_ENERGY : 24, - DESTROY : 25, - RUN : 26, - STOP : 27, - RESET_CODE : 28, - CHECK_AT : 29, - WORLD_ENERGY : 30, - WORLD_ENERGY_UP : 31 + PUT_ENERGY : 20, + STEP : 21, + STEP_OUT : 22, + STEP_IN : 23, + BORN_ORGANISM : 24, + GET_ENERGY : 25, + DESTROY : 26, + RUN : 27, + STOP : 28, + RESET_CODE : 29, + CHECK_AT : 30, + WORLD_ENERGY : 31, + WORLD_ENERGY_UP : 32 }; From 1a3c10eb14e5684c894880523f22bbf441efd1b3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 18:57:44 +0200 Subject: [PATCH 227/291] fixed few tests and added more #83 --- client/src/manager/plugins/Energy.js | 4 ++-- .../src/manager/plugins/organisms/Config.js | 4 ++-- .../plugins/organisms/dos/Operators.js | 2 +- .../plugins/organisms/dos/OperatorsSpec.js | 20 ++++++++++++++++++ .../plugins/organisms/dos/OrganismSpec.js | 21 ++++++++++++------- client/src/vm/VM.js | 19 +++++++++-------- 6 files changed, 48 insertions(+), 22 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 97ae802..cf74462 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -27,7 +27,7 @@ class Energy { } _onIteration(counter) { - Config.worldCleverEnergy && this._cleverActive && this._addCleverBlock(); + Config.worldCleverEnergy && this._cleverActive && this._addCleverEnergyBlock(); if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} if (counter === 0) { @@ -64,7 +64,7 @@ class Energy { this._manager.fire(EVENTS.UPDATE_ENERGY); } - _addCleverBlock() { + _addCleverEnergyBlock() { const width = Config.worldWidth; const height = Config.worldHeight; const color = Helper.rand(Organism.getMaxColors()); diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index a7b14d4..24be983 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -72,7 +72,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 4000, + orgRainMutationPeriod: 10000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -88,7 +88,7 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 4000, + orgCrossoverPeriod: 1000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 304604c..3be7b54 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -163,7 +163,7 @@ class OperatorsDos extends Operators { if (IN_WORLD(x, y)) { this.obs.fire(EVENTS.GET_ENERGY, x, y, this._ret); - this.vars[Num.getVar0(num)] = this._ret.ret; + vars[Num.getVar0(num)] = this._ret.ret; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 9a24191..b72be8a 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -979,4 +979,24 @@ describe("client/src/organism/OperatorsDos", () => { ops1.destroy(); }); }); + + describe('onCheckLeft() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it('Check left, but nothing there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(0); + expect(y).toBe(2); + ret.ret = 0; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckLeft(0x0c7fffff, 0, org)).toEqual(1); // v1=checkLeft() + expect(ops.vars).toEqual([0,0,2,3]); + }); + }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index a162a61..9c62266 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -157,9 +157,9 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking if changes affects color", () => { - const color = org.color; - expect(org.changes).toBe(0); - org.changes = 10; + const color = org.color; + expect(org.color).toBe(color); + org.energy++; expect(org.color).not.toBe(color); }); }); @@ -248,10 +248,15 @@ describe("client/src/organism/OrganismDos", () => { }); it("Checking destroy() method", () => { - let org = new OrganismDos(0, 1, 2, null, () => {}); - - expect(org.energy > 0).toEqual(true); - org.destroy(); - expect(org.energy > 0).toEqual(false); + const org1 = new OrganismDos('0', 1, 2, null); + + expect(org1.energy > 0).toEqual(true); + org1.destroy(); + expect(org1.vm).toBe(null); + expect(org1.energy).toBe(0); + expect(org1.item).toBe(null); + expect(org1.mem).toBe(null); + expect(org1.mutationProbs).toBe(null); + expect(org1.iterations).toBe(-1); }); }); \ No newline at end of file diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 67f8caf..8254ba0 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -86,15 +86,16 @@ class VM extends Observer { * @return {Number} Amount of run lines */ run(org) { - const code = this._code; - const lines = code.length; + const code = this._code; + const lines = code.length; if (lines < 1) {return 0} - const ops = this._ops; - const offs = this._offsets; - const period = OConfig.codeYieldPeriod; - const OFFS = Num.VAR_BITS_OFFS; - let len = period; - let line = this._line; + const ops = this._ops; + const offs = this._offsets; + const period = OConfig.codeYieldPeriod; + const OFFS = Num.VAR_BITS_OFFS; + const WEIGHTS = this._weights; + let len = period; + let line = this._line; let operator; while (len > 0 && org.energy > 0) { @@ -104,7 +105,7 @@ class VM extends Observer { // This is very important peace of logic. As big the organism is // as more energy he spends // - org.energy -= (this._weights[operator] * org.energy); + org.energy -= (WEIGHTS[operator] * org.energy); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 276278fe8ee9583ce9da9d262f844eddf223f287 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 20:23:41 +0200 Subject: [PATCH 228/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index b72be8a..ed3583e 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -987,7 +987,7 @@ describe("client/src/organism/OperatorsDos", () => { beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); afterEach (() => {ops.destroy(); org.destroy()}); - it('Check left, but nothing there', () => { + it('Checks left, but nothing there', () => { org.on(EVENTS.CHECK_AT, (x, y, ret) => { expect(x).toBe(0); expect(y).toBe(2); @@ -998,5 +998,36 @@ describe("client/src/organism/OperatorsDos", () => { expect(ops.onCheckLeft(0x0c7fffff, 0, org)).toEqual(1); // v1=checkLeft() expect(ops.vars).toEqual([0,0,2,3]); }); + + it('Checks left and energy there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(0); + expect(y).toBe(2); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckLeft(0x0c7fffff, 1, org)).toEqual(2); // v1=checkLeft() + expect(ops.vars).toEqual([0,9,2,3]); + }); + + it('Checks left with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(0); + expect(y).toBe(2); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops1.onCheckLeft(0x0c7fffff, 1, org)).toEqual(2); // v7=checkLeft() + expect(ops1.vars).toEqual([0,1,2,3,4,5,6,9,8,9,10,11,12,13,14,15]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); }); }); \ No newline at end of file From b4cd276a63f8907f9ad2be39681b496bb2b7366f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 21:28:20 +0200 Subject: [PATCH 229/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 51 +++++++++++++++++++ .../plugins/organisms/dos/OrganismSpec.js | 2 + 2 files changed, 53 insertions(+) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index ed3583e..32f6d8d 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1030,4 +1030,55 @@ describe("client/src/organism/OperatorsDos", () => { ops1.destroy(); }); }); + + describe('onCheckRight() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it('Checks right, but nothing there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 0; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckRight(0x0c7fffff, 0, org)).toEqual(1); // v1=checkLeft() + expect(ops.vars).toEqual([0,0,2,3]); + }); + + it('Checks right and energy there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v1=checkLeft() + expect(ops.vars).toEqual([0,9,2,3]); + }); + + it('Checks right with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(2); + expect(y).toBe(2); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops1.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v7=checkLeft() + expect(ops1.vars).toEqual([0,1,2,3,4,5,6,9,8,9,10,11,12,13,14,15]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 9c62266..2aa816b 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -94,6 +94,7 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); OConfig.codeYieldPeriod = 1; const org1 = new OrganismDos('0', 1, 2, null); + _fill(org1.vm.vars, 0); org1.vm.insertLine(); expect(org1.energy).toBe(100); @@ -234,6 +235,7 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); const org1 = new OrganismDos('0', 1, 2, null); + _fill(org1.vm.vars, 0); org1.vm.insertLine(); org1.energy = OConfig.orgCloneMinEnergy * 2; org1.on(OEvents.CLONE, () => flag = true); From 0c4f2a3435d8bcd54f26fc951be7f34f318be54f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 21:33:12 +0200 Subject: [PATCH 230/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 32f6d8d..91a3319 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1046,7 +1046,7 @@ describe("client/src/organism/OperatorsDos", () => { }); org.x = 1; org.y = 2; - expect(ops.onCheckRight(0x0c7fffff, 0, org)).toEqual(1); // v1=checkLeft() + expect(ops.onCheckRight(0x0c7fffff, 0, org)).toEqual(1); // v1=checkRight() expect(ops.vars).toEqual([0,0,2,3]); }); @@ -1058,7 +1058,7 @@ describe("client/src/organism/OperatorsDos", () => { }); org.x = 1; org.y = 2; - expect(ops.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v1=checkLeft() + expect(ops.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v1=checkRight() expect(ops.vars).toEqual([0,9,2,3]); }); @@ -1074,7 +1074,109 @@ describe("client/src/organism/OperatorsDos", () => { }); org.x = 1; org.y = 2; - expect(ops1.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v7=checkLeft() + expect(ops1.onCheckRight(0x0c7fffff, 1, org)).toEqual(2); // v7=checkRight() + expect(ops1.vars).toEqual([0,1,2,3,4,5,6,9,8,9,10,11,12,13,14,15]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + }); + + describe('onCheckUp() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it('Checks up, but nothing there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(1); + ret.ret = 0; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckUp(0x0c7fffff, 0, org)).toEqual(1); // v1=checkUp() + expect(ops.vars).toEqual([0,0,2,3]); + }); + + it('Checks up and energy there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(1); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckUp(0x0c7fffff, 1, org)).toEqual(2); // v1=checkUp() + expect(ops.vars).toEqual([0,9,2,3]); + }); + + it('Checks up with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(1); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops1.onCheckUp(0x0c7fffff, 1, org)).toEqual(2); // v7=checkUp() + expect(ops1.vars).toEqual([0,1,2,3,4,5,6,9,8,9,10,11,12,13,14,15]); + + OConfig.codeBitsPerVar = bpv; + ops1.destroy(); + }); + }); + + describe('onCheckDown() method', () => { + let org; + let ops; + + beforeEach(() => {org = new OrganismDos('0', 0, 0, {}); ops = new OperatorsDos([], [0, 1, 2, 3], org)}); + afterEach (() => {ops.destroy(); org.destroy()}); + + it('Checks down, but nothing there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 0; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckDown(0x0c7fffff, 0, org)).toEqual(1); // v1=checkDown() + expect(ops.vars).toEqual([0,0,2,3]); + }); + + it('Checks down and energy there', () => { + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops.onCheckDown(0x0c7fffff, 1, org)).toEqual(2); // v1=checkDown() + expect(ops.vars).toEqual([0,9,2,3]); + }); + + it('Checks right with 4 bits per var', () => { + let bpv = OConfig.codeBitsPerVar; + OConfig.codeBitsPerVar = 4; + let ops1 = new OperatorsDos([1], [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], org); + + org.on(EVENTS.CHECK_AT, (x, y, ret) => { + expect(x).toBe(1); + expect(y).toBe(3); + ret.ret = 9; + }); + org.x = 1; + org.y = 2; + expect(ops1.onCheckDown(0x0c7fffff, 1, org)).toEqual(2); // v7=checkDown() expect(ops1.vars).toEqual([0,1,2,3,4,5,6,9,8,9,10,11,12,13,14,15]); OConfig.codeBitsPerVar = bpv; From 39cbb6222ec08a2c9c1a38f37195a466c2658996 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 21:45:00 +0200 Subject: [PATCH 231/291] just for test... --- client/src/vm/VM.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 8254ba0..7c4feff 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -265,7 +265,7 @@ class VM extends Observer { /** * Generates default variables vm. It should be in ES5 version, because * speed is important. Amount of vars depends on OConfig.codeBitsPerVar config. - * @returns {Array} vars vm + * @returns {Array} Filled variable array */ _getVars() { if (this._vars && this._vars.length > 0) {return this._vars} From c4b08642e70554eae21f9a727095f6d40b501d3f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Feb 2018 22:04:50 +0200 Subject: [PATCH 232/291] fixed few more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 91a3319..aac22f1 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1,3 +1,5 @@ +const _fill = require('lodash/fill'); + describe("client/src/organism/OperatorsDos", () => { let OConfig = require('./../../organisms/Config'); let cbpv = OConfig.codeBitsPerVar; @@ -6,8 +8,6 @@ describe("client/src/organism/OperatorsDos", () => { let EVENTS = require('./../../../../share/Events').EVENTS; let Config = require('./../../../../share/Config').Config; let OrganismDos = require('./../../organisms/dos/Organism'); - //let OEvents = require('./../../organisms/Organism').EVENTS; - //let api = require('./../../../../share/Config').api; afterAll(() => OConfig.codeBitsPerVar = cbpv); @@ -1183,4 +1183,36 @@ describe("client/src/organism/OperatorsDos", () => { ops1.destroy(); }); }); + + describe('Checks complex DOS scripts for validness', () => { + let org; + + beforeEach(() => org = new OrganismDos('0', 0, 0, {})); + afterEach (() => org.destroy()); + + /** + * if (v0===v1) { // true + * v3=0x7fff + * } + */ + it('Checks if operator', () => { + const yieldPeriod = OConfig.codeYieldPeriod; + const weights = OConfig.orgOperatorWeights.slice(); + const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + _fill(org.vm.vars, 0); + org.energy = 100; + OConfig.codeYieldPeriod = 2; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + + org.vm.insertLine(); + org.vm.insertLine(); + org.vm.updateLine(0, 0x021abfff); + org.vm.updateLine(1, 0x01dfffff); + org.vm.run(org); + expect(org.vm.vars).toEqual([0,0,0,0x7fff]); + + OConfig.codeYieldPeriod = yieldPeriod; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + }); + }); }); \ No newline at end of file From e59aa6c329997adbdcff6ac06a0946e195b7c3aa Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 25 Feb 2018 01:09:09 +0200 Subject: [PATCH 233/291] merger simple and clever energy. from now, it's just energy --- client/src/manager/plugins/Energy.js | 43 +++------------ .../src/manager/plugins/organisms/Config.js | 20 ++----- .../src/manager/plugins/organisms/Organism.js | 4 +- .../manager/plugins/organisms/Organisms.js | 7 +-- client/src/share/Config.js | 39 +++----------- client/src/share/Events.js | 53 +++++++++---------- 6 files changed, 50 insertions(+), 116 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index cf74462..a3a7301 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -27,48 +27,21 @@ class Energy { } _onIteration(counter) { - Config.worldCleverEnergy && this._cleverActive && this._addCleverEnergyBlock(); + this._cleverActive && this._addEnergyBlock(); - if (counter % Config.worldEnergyCheckPeriod !== 0 || Config.worldEnergyCheckPeriod === 0) {return} - if (counter === 0) { - this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); - return; - } + if (Config.worldEnergyCheckPeriod === 0 || counter % Config.worldEnergyCheckPeriod !== 0) {return} - const energy = this._getWorldEnergy(); + const energy = this._getEnergyPercent(); this._manager.fire(EVENTS.WORLD_ENERGY, energy); - if (energy <= Config.worldCleverEnergyMinPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = true)} - else if (energy >= Config.worldCleverEnergyMaxPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = false)} - - if (energy <= Config.worldEnergyCheckAmount) { - this._updateEnergy(Config.worldEnergyDots, Config.worldEnergyInDot); - } - } - - _updateEnergy(dotAmount, energyInDot) { - const world = this._manager.world; - const width = Config.worldWidth; - const height = Config.worldHeight; - const rand = Helper.rand; - let x; - let y; - - Console.info('Creating random energy'); - for (let dot = 0; dot < dotAmount; dot++) { - x = rand(width); - y = rand(height); - if (world.getDot(x, y) < 1) { - world.setDot(x, y, energyInDot); - } - } - this._manager.fire(EVENTS.UPDATE_ENERGY); + if (energy < Config.worldEnergyMinPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = true)} + else if (energy > Config.worldEnergyMaxPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = false)} } - _addCleverEnergyBlock() { + _addEnergyBlock() { const width = Config.worldWidth; const height = Config.worldHeight; const color = Helper.rand(Organism.getMaxColors()); - let block = Config.worldCleverEnergyBlockSize; + let block = Config.worldEnergyBlockSize; const world = this._manager.world; let x = Helper.rand(width); let y = Helper.rand(height); @@ -83,7 +56,7 @@ class Energy { } } - _getWorldEnergy() { + _getEnergyPercent() { let energy = 0; const world = this._manager.world; const width = Config.worldWidth; diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 24be983..06d20d5 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -49,19 +49,9 @@ const Config = { */ orgMutationPerOrg: false, /** - * {Number} Minimum energy for one organism, which will be multiplied on - * organism code size. This value permits organism to have a baby (clone). - * If amount of energy less then orgCloneMinEnergy * vm.size, then clone - * is not possible + * {Number} Minimum age for cloning. Before that, cloning is impossible */ - orgCloneMinEnergy: 100000, - /** - * {Boolean} true means, that one organism will be killed just after new - * organism has cloned. If population is less then orgMaxOrgs, then no killing - * will be provided. Killing of organism will be done using random organism - * selection from population - */ - //orgKillOnClone: false, + orgCloneMinAge: 5000, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -124,11 +114,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 500, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 1000, + orgStartAmount: 500, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created @@ -178,7 +168,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 300 + codeMaxSize: 1000 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 70d1ea5..9c96fdb 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -239,9 +239,7 @@ class Organism extends Observer { } _updateClone() { - if ((this._energy > OConfig.orgCloneMinEnergy * this.vm.size) && this._energy > 0) { - this.fire(CLONE, this); - } + if (this._iterations > OConfig.orgCloneMinAge && this._energy > 0) {this.fire(CLONE, this)} } /** diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index a0235e2..b6378e9 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -275,7 +275,7 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - const maxOrgs = OConfig.orgMaxOrgs; + const maxOrgs = OConfig.orgMaxOrgs; //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} @@ -293,10 +293,7 @@ class Organisms extends Configurable { // organisms before cloning. They should kill each other to have a possibility // to clone them. // - if (this.organisms.size < maxOrgs && this._clone(org)) { - org.energy -= (OConfig.orgCloneMinEnergy * org.vm.size / 2); - this.organisms.last.val.energy -= (OConfig.orgCloneMinEnergy * this.organisms.last.val.vm.size / 2) - } + this.organisms.size < maxOrgs && this._clone(org); } _killInTour() { diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 6dd4228..c5adaa7 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -52,11 +52,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 * 2, + worldWidth: 1920 / 2, /** * {Number} World height */ - worldHeight: 1080 * 2, + worldHeight: 1080 / 2, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -66,51 +66,28 @@ ClientConfig.init({ * calculations). */ worldCyclical: false, - /** - * {Number} Minimum percent of energy in current world. Under percent i mean - * percent from possible world fulfilled by energy with value 0xffffffff. If - * the energy will be less or equal then this value, then new random energy - * should be added. - */ - worldEnergyCheckAmount: .0001, /** * {Number} An amount of iteration, after which we have to check world energy - * amount. Works in pair with worldEnergyCheckAmount. May be 0 if - * you want to disable it + * percent. May be 0 if you want to disable energy generation */ worldEnergyCheckPeriod: 5000, - /** - * {Number} Amount of energy blocks in a world. Blocks will be placed in a - * random way... - */ - worldEnergyDots: 10000, - /** - * {Number} Amount of energy in every block. See worldEnergyDots - * config for details. - */ - worldEnergyInDot: 0x00ddff, - /** - * {Boolean} Analog of trees. This type of energy is growing all the time - * using random walk algorithm. - */ - worldCleverEnergy: true, /** * {Number} size of one clever energy block in dots. */ - worldCleverEnergyBlockSize: 400, + worldEnergyBlockSize: 400, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will - * be less then worldCleverEnergyMinPercent. These two configs create cyclical + * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldCleverEnergyMaxPercent: .0008, + worldEnergyMaxPercent: .0008, /** - * {Number} Opposite to worldCleverEnergyMaxPercent. Sets minimum percent from + * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldCleverEnergyMinPercent: .00008, + worldEnergyMinPercent: .00002, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/share/Events.js b/client/src/share/Events.js index 9f8c421..d099c33 100644 --- a/client/src/share/Events.js +++ b/client/src/share/Events.js @@ -13,33 +13,32 @@ const EVENTS = { CODE_RUN : 3, BACKUP : 4, CLONE : 5, - UPDATE_ENERGY : 6, - KILL : 7, // general kill event - KILL_TOUR : 8, // killed during organisms tournament - KILL_NO_ENERGY : 9, // killed if zero energy - KILL_AGE : 10, // killed if max age reached - KILL_EAT : 11, // killed, because other organism has eat this one - KILL_OVERFLOW : 12, // population reaches it's maximum, we have to kill one organism - KILL_STEP_OUT : 13, // killed, because organism step outside the world - KILL_STEP_IN : 14, // killed, because of punishment for step in from near client - KILL_CLONE : 15, // killed, because of lack of energy after clone - MUTATIONS : 16, - EAT : 17, - EAT_ORG : 18, - EAT_ENERGY : 19, - PUT_ENERGY : 20, - STEP : 21, - STEP_OUT : 22, - STEP_IN : 23, - BORN_ORGANISM : 24, - GET_ENERGY : 25, - DESTROY : 26, - RUN : 27, - STOP : 28, - RESET_CODE : 29, - CHECK_AT : 30, - WORLD_ENERGY : 31, - WORLD_ENERGY_UP : 32 + KILL : 6, // general kill event + KILL_TOUR : 7, // killed during organisms tournament + KILL_NO_ENERGY : 8, // killed if zero energy + KILL_AGE : 9, // killed if max age reached + KILL_EAT : 10, // killed, because other organism has eat this one + KILL_OVERFLOW : 11, // population reaches it's maximum, we have to kill one organism + KILL_STEP_OUT : 12, // killed, because organism step outside the world + KILL_STEP_IN : 13, // killed, because of punishment for step in from near client + KILL_CLONE : 14, // killed, because of lack of energy after clone + MUTATIONS : 15, + EAT : 16, + EAT_ORG : 17, + EAT_ENERGY : 18, + PUT_ENERGY : 19, + STEP : 20, + STEP_OUT : 21, + STEP_IN : 22, + BORN_ORGANISM : 23, + GET_ENERGY : 24, + DESTROY : 25, + RUN : 26, + STOP : 27, + RESET_CODE : 28, + CHECK_AT : 29, + WORLD_ENERGY : 30, + WORLD_ENERGY_UP : 31 }; From 434205199d7ee97658e86058ffa8b35042169d28 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 25 Feb 2018 01:24:32 +0200 Subject: [PATCH 234/291] small refactoring --- client/src/manager/plugins/organisms/Config.js | 3 ++- client/src/manager/plugins/organisms/Organisms.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 06d20d5..fa01e2d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -49,7 +49,8 @@ const Config = { */ orgMutationPerOrg: false, /** - * {Number} Minimum age for cloning. Before that, cloning is impossible + * {Number} Minimum age for cloning. Before that, cloning is impossible. It should + * be less then orgAlivePeriod config */ orgCloneMinAge: 5000, /** diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index b6378e9..6e5dc36 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -275,7 +275,7 @@ class Organisms extends Configurable { } _onCloneOrg(org) { - const maxOrgs = OConfig.orgMaxOrgs; + //const maxOrgs = OConfig.orgMaxOrgs; //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} @@ -293,7 +293,7 @@ class Organisms extends Configurable { // organisms before cloning. They should kill each other to have a possibility // to clone them. // - this.organisms.size < maxOrgs && this._clone(org); + this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); } _killInTour() { From f2d819546d86c32d0dc04ff04cea294ad7cb06d7 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 25 Feb 2018 11:17:38 +0200 Subject: [PATCH 235/291] fixed incorrect ips calculation with different Yield values changed default loop weight config --- client/src/manager/plugins/organisms/Config.js | 14 +++++++------- client/src/manager/plugins/status/Status.js | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index fa01e2d..bab779c 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. */ orgOperatorWeights: [ - .000001, .00001, .000001, .00000001, .000001, // var, const, if, loop, operator, - .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, - .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, - .000001, .000001, // fromMem, toMem, - .000001, .000001, // myX, myY, - .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown + .000001, .00001, .000001, .000000001, .000001, // var, const, if, loop, operator, + .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, + .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, + .000001, .000001, // fromMem, toMem, + .000001, .000001, // myX, myY, + .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown ], /** * {Array} Probabilities which used, when mutator decides what to do: @@ -161,7 +161,7 @@ const Config = { * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. */ - codeIterationsPerOnce: 200, + codeIterationsPerOnce: 100, /** * {Number} If organism reach this limit of amount of vm lines, then codeSizeCoef * will be used during it's energy grabbing by system. We use this approach, diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index ec58c8e..fae69d8 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -19,6 +19,7 @@ const Helper = require('./../../../../../common/src/Helper'); const EVENTS = require('./../../../share/Events').EVENTS; const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; +const OConfig = require('./../../../manager/plugins/organisms/Config'); class Status extends Configurable { static _toFixed(val, fixed) { @@ -173,7 +174,7 @@ class Status extends Configurable { this._onBeforeLoop(orgs); - status.ips = fix(this._ips / this._ipsTimes, 2); + status.ips = fix(this._ips / this._ipsTimes * OConfig.codeYieldPeriod, 2); status.lps = fix((this.parent.codeRuns - this._codeRuns) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); From fa1edd542ed53e8283b897dc940485dacc040535 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 25 Feb 2018 12:36:19 +0200 Subject: [PATCH 236/291] fixed more tests #83 --- client/src/manager/plugins/organisms/Config.js | 2 +- .../src/manager/plugins/organisms/dos/Operators.js | 2 +- .../manager/plugins/organisms/dos/OrganismSpec.js | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index bab779c..569660f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -89,7 +89,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 40000, + orgAlivePeriod: 30000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 3be7b54..1adfef5 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -136,7 +136,7 @@ class OperatorsDos extends Operators { } /** - * while(v0 op v2) goto offs + * while(v0 op v1) goto offs */ onLoop(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 2aa816b..bc19c68 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -224,26 +224,30 @@ describe("client/src/organism/OrganismDos", () => { }); describe('Clonning', () => { - it('Organism should fire CLONE event if enough energy', () => { + it('Organism should fire CLONE event if enough age', () => { let flag = false; - const minEnergy = OConfig.orgCloneMinEnergy; + const minAge = OConfig.orgCloneMinAge; const yieldPeriod = OConfig.codeYieldPeriod; const weights = OConfig.orgOperatorWeights.slice(); const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; - OConfig.orgCloneMinEnergy = 100; + OConfig.orgCloneMinAge = 1; OConfig.codeYieldPeriod = 1; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); const org1 = new OrganismDos('0', 1, 2, null); _fill(org1.vm.vars, 0); org1.vm.insertLine(); - org1.energy = OConfig.orgCloneMinEnergy * 2; + org1.energy = 100; org1.on(OEvents.CLONE, () => flag = true); org1.run(); + expect(flag).toBe(false); + org1.run(); + expect(flag).toBe(false); + org1.run(); expect(flag).toBe(true); org1.destroy(); - OConfig.orgCloneMinEnergy = minEnergy; + OConfig.orgCloneMinAge = minAge; OConfig.codeYieldPeriod = yieldPeriod; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); }) From 8d39ced9049b25c181d90e5966a2c73a4fd5ff78 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 25 Feb 2018 21:59:42 +0200 Subject: [PATCH 237/291] fixed critical issue in block operators (if, while) #83 added complex tests for if operator #83 --- .../plugins/organisms/dos/Operators.js | 16 +++ .../plugins/organisms/dos/OperatorsSpec.js | 116 ++++++++++++++---- client/src/vm/VM.js | 2 +- 3 files changed, 106 insertions(+), 28 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 1adfef5..6819a6e 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -118,11 +118,27 @@ class OperatorsDos extends Operators { return ++line; } + /** + * Handler of numeric constant assignment operator. 'xx' means, that amount of + * bits depends on configuration. Example: + * bits : 8 xx xx + * number: 00000001 00 01... + * desc : const v0 1 + * string: v0 = 1 + */ onConst(num, line) { this.vars[Num.getVar0(num)] = Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.codeConstBits); return ++line; } + /** + * Handler of 'if' operator. 'xx' means, that amount of bits depends on + * configuration. Example: + * bits : 8 xx xx 2 xx + * number: 00000010 00 01 00 00... + * desc : if v0 v1 < } + * string: if (v0 < v1) {} + */ onCondition(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); const offs = this._getOffs(line, Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock)); diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index aac22f1..64cbea7 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1,13 +1,14 @@ const _fill = require('lodash/fill'); describe("client/src/organism/OperatorsDos", () => { - let OConfig = require('./../../organisms/Config'); - let cbpv = OConfig.codeBitsPerVar; + const OConfig = require('./../../organisms/Config'); + const cbpv = OConfig.codeBitsPerVar; OConfig.codeBitsPerVar = 2; - let OperatorsDos = require('./Operators'); - let EVENTS = require('./../../../../share/Events').EVENTS; - let Config = require('./../../../../share/Config').Config; - let OrganismDos = require('./../../organisms/dos/Organism'); + const OperatorsDos = require('./Operators'); + const EVENTS = require('./../../../../share/Events').EVENTS; + const Config = require('./../../../../share/Config').Config; + const OrganismDos = require('./../../organisms/dos/Organism'); + const ConfigHelper = require('./../../../../../../common/tests/Config'); afterAll(() => OConfig.codeBitsPerVar = cbpv); @@ -1185,34 +1186,95 @@ describe("client/src/organism/OperatorsDos", () => { }); describe('Checks complex DOS scripts for validness', () => { - let org; + const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + const weights = OConfig.orgOperatorWeights.slice(); + let ocfg; + let org; + const script = code => { + for (let i = 0; i < code.length; i++) {org.vm.insertLine()} + for (let i = 0; i < code.length; i++) {org.vm.updateLine(i, typeof code[i] === 'string' ? parseInt(code[i].split(' ').join(''), 2) : code[i])} + OConfig.codeYieldPeriod = code.length; + }; - beforeEach(() => org = new OrganismDos('0', 0, 0, {})); - afterEach (() => org.destroy()); - /** - * if (v0===v1) { // true - * v3=0x7fff - * } - */ - it('Checks if operator', () => { - const yieldPeriod = OConfig.codeYieldPeriod; - const weights = OConfig.orgOperatorWeights.slice(); - const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + beforeEach(() => { + ocfg = new ConfigHelper(OConfig); + ocfg.set('codeYieldPeriod', 2); + ocfg.set('codeBitsPerBlock', 8); + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + + org = new OrganismDos('0', 0, 0, {}); _fill(org.vm.vars, 0); org.energy = 100; - OConfig.codeYieldPeriod = 2; - OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + }); + afterEach (() => { + org.destroy(); + ocfg.reset(); + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + }); - org.vm.insertLine(); - org.vm.insertLine(); - org.vm.updateLine(0, 0x021abfff); - org.vm.updateLine(1, 0x01dfffff); + /** + * if (v0 === v1) { // true + * v3 = 0x7fff + * } + */ + it('if should go inside the block, if condition is true', () => { + script([0x021abfff, 0x01dfffff]); org.vm.run(org); expect(org.vm.vars).toEqual([0,0,0,0x7fff]); - - OConfig.codeYieldPeriod = yieldPeriod; - OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + }); + /** + * if (v0 === v1) {} // true + * v3 = 0x7fff + */ + it('if without body should go to the next row, if condition is true', () => { + script([0x021803ff, 0x01dfffff]); + org.vm.run(org); + expect(org.vm.vars).toEqual([0,0,0,0x7fff]); + }); + /** + * v0 = 1 + * if (v0 === v1) {} // true + * v0 = 0 + */ + it('Checks if operator without body and with other code around', () => { + script([0x0100007f, 0x021803ff, 0x0100003f]); + org.vm.run(org); + expect(org.vm.vars).toEqual([0,0,0,0]); + }); + /** + * if (v0 === v1) { // true + * if (v0 === v1) {} // true + * v0 = 1 + * } + * v1 = 1 + */ + it('Checks if inside if with true condition', () => { + script([ + '10 00 01 10 00000010 1111111111', + '10 00 01 10 00000001 1111111111', + '01 00 0000000000000001 111111', + '01 01 0000000000000001 111111' + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([1,1,0,0]); + }); + /** + * if (v0 !== v1) { // false + * if (v0 === v1) {} // true + * v0 = 1 + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '10 00 01 11 00000010 1111111111', + '10 00 01 10 00000001 1111111111', + '01 00 0000000000000001 111111', + '01 01 0000000000000001 111111' + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([0,1,0,0]); }); }); }); \ No newline at end of file diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 7c4feff..a957784 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -110,7 +110,7 @@ class VM extends Observer { // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) // - if (offs.length > 1 && line === offs[offs.length - 1]) { + while (offs.length > 1 && line === offs[offs.length - 1]) { offs.pop(); line = offs.pop(); } From 81049a20a7b77cd19b294097f3ef1d2a997c4712 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 26 Feb 2018 00:29:47 +0200 Subject: [PATCH 238/291] fixed more tests #83 from now code size affects energy waste --- .../plugins/organisms/dos/OperatorsSpec.js | 54 +++++++++++++++++-- .../plugins/organisms/dos/OrganismSpec.js | 4 +- client/src/vm/VM.js | 20 +++---- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 64cbea7..9aae12f 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1,4 +1,5 @@ const _fill = require('lodash/fill'); +//const C2S = require('./Code2String'); describe("client/src/organism/OperatorsDos", () => { const OConfig = require('./../../organisms/Config'); @@ -1199,8 +1200,12 @@ describe("client/src/organism/OperatorsDos", () => { beforeEach(() => { ocfg = new ConfigHelper(OConfig); - ocfg.set('codeYieldPeriod', 2); - ocfg.set('codeBitsPerBlock', 8); + ocfg.set('codeYieldPeriod', 2); + ocfg.set('codeBitsPerBlock', 8); + ocfg.set('codeBitsPerOperator', 8); + ocfg.set('codeBitsPerVar', 2); + ocfg.set('codeConstBits', 16); + ocfg.set('orgMemBits', 8); OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); org = new OrganismDos('0', 0, 0, {}); @@ -1262,7 +1267,7 @@ describe("client/src/organism/OperatorsDos", () => { /** * if (v0 !== v1) { // false * if (v0 === v1) {} // true - * v0 = 1 + * v0 = 1 * } * v1 = 1 */ @@ -1276,5 +1281,48 @@ describe("client/src/organism/OperatorsDos", () => { org.vm.run(org); expect(org.vm.vars).toEqual([0,1,0,0]); }); + /** + * if (v0 !== v1) { // false + * if (v0 === v1) { // true + * v0 = 3 + * } + * v0 = 2 + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '10 00 01 11 00000011 1111111111', + '10 00 01 10 00000010 1111111111', + '01 00 0000000000000011 111111', + '01 00 0000000000000010 111111', + '01 01 0000000000000001 111111' + ]); + OConfig.codeYieldPeriod = 2; + org.vm.run(org); + expect(org.vm.vars).toEqual([0,1,0,0]); + }); + /** + * if (v0 === v1) { // true + * if (v0 === v1) { // true + * v0 = 3 + * } + * v0 = 2 + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '10 00 01 10 00000011 1111111111', + '10 00 01 10 00000010 1111111111', + '01 00 0000000000000011 111111', + '01 00 0000000000000010 111111', + '01 01 0000000000000001 111111' + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([2,1,0,0]); + }); + //const c2s = new C2S({api: {}}); + //c2s.format(org.vm.code); }); }); \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index bc19c68..27281c9 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -99,9 +99,9 @@ describe("client/src/organism/OrganismDos", () => { expect(org1.energy).toBe(100); org1.run(); - expect(org1.energy).toBe(90); // 100 - 100 * .1 = 90 + expect(org1.energy).toBe(89); // 100 - (100 * .1 + 1) = 89 org1.run(); - expect(org1.energy).toBe(81); // 90 - 90 * .1 = 81 + expect(org1.energy).toBe(79.1); // 90 - (90 * .1 + 1) = 79.1 org1.destroy(); expect(org1.energy < 1).toBe(true); diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index a957784..1711d9b 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -86,16 +86,16 @@ class VM extends Observer { * @return {Number} Amount of run lines */ run(org) { - const code = this._code; - const lines = code.length; + const code = this._code; + const lines = code.length; if (lines < 1) {return 0} - const ops = this._ops; - const offs = this._offsets; - const period = OConfig.codeYieldPeriod; - const OFFS = Num.VAR_BITS_OFFS; - const WEIGHTS = this._weights; - let len = period; - let line = this._line; + const ops = this._ops; + const offs = this._offsets; + const period = OConfig.codeYieldPeriod; + const OFFS = Num.VAR_BITS_OFFS; + const WEIGHTS = this._weights; + let len = period; + let line = this._line; let operator; while (len > 0 && org.energy > 0) { @@ -105,7 +105,7 @@ class VM extends Observer { // This is very important peace of logic. As big the organism is // as more energy he spends // - org.energy -= (WEIGHTS[operator] * org.energy); + org.energy -= (WEIGHTS[operator] * org.energy + (org.vm ? org.vm.size : 0)); // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 0816b6a357afbc68843fd70fac906bb8d73b6c0c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 26 Feb 2018 11:07:04 +0200 Subject: [PATCH 239/291] fixed more tests #83 --- .../plugins/organisms/dos/Operators.js | 30 ++++++++++++++----- .../plugins/organisms/dos/OperatorsSpec.js | 17 +++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 6819a6e..5fef396 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -106,12 +106,17 @@ class OperatorsDos extends Operators { get operators() {return this._OPERATORS_CB} /** - * Parses variable operator. Format: var = number|var. 'num' bits format: - * TODO: + * Handler of variable assignment operator. 'xx' means, that amount of + * bits depends on configuration. '...' means, that all other bits are + * ignored. Example: + * bits : 8 xx xx + * number: 00000000 00 01... + * desc : var v0 v1 + * string: v0 = v1 * - * @param {Number} num Packed into number vm line - * @param {Number} line Current line in vm - * @return {Number} Parsed vm line string + * @param {Number} num One bit packed byte code row + * @param {Number} line Current line in DOS code + * @return {Number} Next line number to proceed */ onVar(num, line) { this.vars[Num.getVar0(num)] = this.vars[Num.getVar1(num)]; @@ -120,11 +125,16 @@ class OperatorsDos extends Operators { /** * Handler of numeric constant assignment operator. 'xx' means, that amount of - * bits depends on configuration. Example: + * bits depends on configuration. '...' means, that all other bits are + * ignored. Example: * bits : 8 xx xx * number: 00000001 00 01... * desc : const v0 1 * string: v0 = 1 + * + * @param {Number} num One bit packed byte code row + * @param {Number} line Current line in DOS code + * @return {Number} Next line number to proceed */ onConst(num, line) { this.vars[Num.getVar0(num)] = Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.codeConstBits); @@ -133,11 +143,17 @@ class OperatorsDos extends Operators { /** * Handler of 'if' operator. 'xx' means, that amount of bits depends on - * configuration. Example: + * configuration. '...' means, that all other bits are + * ignored. Offset of closing bracket means row number after, which this + * bracket will be added. Example: * bits : 8 xx xx 2 xx * number: 00000010 00 01 00 00... * desc : if v0 v1 < } * string: if (v0 < v1) {} + * + * @param {Number} num One bit packed byte code row + * @param {Number} line Current line in DOS code + * @return {Number} Next line number to proceed */ onCondition(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 9aae12f..35f3452 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1322,6 +1322,23 @@ describe("client/src/organism/OperatorsDos", () => { org.vm.run(org); expect(org.vm.vars).toEqual([2,1,0,0]); }); + /** + * if (v0 === v1) { // true + * v0 = 2 + * if (v0 === v1) {} // false + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '10 00 01 10 00000010 1111111111', + '01 00 0000000000000010 111111', + '10 00 01 10 00000010 1111111111', + '01 01 0000000000000001 111111', + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([2,1,0,0]); + }); //const c2s = new C2S({api: {}}); //c2s.format(org.vm.code); }); From 44cf5ba1ca873cd3a35e855a18c2435691d9c6ae Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 26 Feb 2018 13:15:38 +0200 Subject: [PATCH 240/291] fixed more tests #83 --- .../manager/plugins/organisms/dos/Operators.js | 3 ++- .../plugins/organisms/dos/OperatorsSpec.js | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 5fef396..eda9f89 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -145,7 +145,8 @@ class OperatorsDos extends Operators { * Handler of 'if' operator. 'xx' means, that amount of bits depends on * configuration. '...' means, that all other bits are * ignored. Offset of closing bracket means row number after, which this - * bracket will be added. Example: + * bracket will be added. Offset of closing bracket is calculating using + * formula: line + offs. Example: * bits : 8 xx xx 2 xx * number: 00000010 00 01 00 00... * desc : if v0 v1 < } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 35f3452..3c45882 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1339,6 +1339,24 @@ describe("client/src/organism/OperatorsDos", () => { org.vm.run(org); expect(org.vm.vars).toEqual([2,1,0,0]); }); + /** + * if (v0 === v1) { // true + * if (v0 === v1) { // true + * v0 = 2 + * } + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '10 00 01 10 00000010 1111111111', + '10 00 01 10 00000001 1111111111', + '01 00 0000000000000010 111111', + '01 01 0000000000000001 111111', + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([2,1,0,0]); + }); //const c2s = new C2S({api: {}}); //c2s.format(org.vm.code); }); From 30bdb8db250879e0df30b4f31dfb2439add68234 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 26 Feb 2018 20:47:39 +0200 Subject: [PATCH 241/291] critical issue with incorrect world energy calculation has fixed changed default operators weights --- client/src/manager/plugins/Energy.js | 3 +-- client/src/manager/plugins/organisms/Config.js | 12 ++++++------ client/src/share/Config.js | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index a3a7301..788abde 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -6,7 +6,6 @@ const Helper = require('./../../../../common/src/Helper'); const Config = require('./../../share/Config').Config; const Organism = require('./../../manager/plugins/organisms/Organism').Organism; -const Console = require('./../../share/Console'); const EVENTS = require('./../../share/Events').EVENTS; const POSID = Helper.posId; @@ -61,7 +60,7 @@ class Energy { const world = this._manager.world; const width = Config.worldWidth; const height = Config.worldHeight; - const orgs = this._manager.organisms; + const orgs = this._manager.positions; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 569660f..4f28b4d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. */ orgOperatorWeights: [ - .000001, .00001, .000001, .000000001, .000001, // var, const, if, loop, operator, - .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, - .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, - .000001, .000001, // fromMem, toMem, - .000001, .000001, // myX, myY, - .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown + .000001, .000001, .00000001, .00000000001, .0000001, // var, const, if, loop, operator, + .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, + .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, + .000001, .000001, // fromMem, toMem, + .0000001, .0000001, // myX, myY, + .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown ], /** * {Array} Probabilities which used, when mutator decides what to do: diff --git a/client/src/share/Config.js b/client/src/share/Config.js index c5adaa7..63f07c2 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -74,20 +74,20 @@ ClientConfig.init({ /** * {Number} size of one clever energy block in dots. */ - worldEnergyBlockSize: 400, + worldEnergyBlockSize: 200, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldEnergyMaxPercent: .0008, + worldEnergyMaxPercent: .0009, /** * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldEnergyMinPercent: .00002, + worldEnergyMinPercent: .0001, /** * {Number} Zoom speed 0..1 */ From e57a3dd3253eadf9ed17146788cf41a0e0630136 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 27 Feb 2018 09:54:29 +0200 Subject: [PATCH 242/291] refactoring --- .gitignore | 1 + client/src/manager/plugins/Energy.js | 10 ++++------ client/src/manager/plugins/organisms/Organisms.js | 11 +++++------ client/src/manager/plugins/organisms/dos/Organisms.js | 11 +++-------- 4 files changed, 13 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 32f2926..0d80782 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ desktop.ini /client/dist/app.js.map /client/dist/app.js /.idea +/pics/life-has-created.png diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 788abde..30c7f81 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -48,10 +48,8 @@ class Energy { for (let i = 0; i < block; i++) { x = x + Helper.rand(3) - 1; y = y + Helper.rand(3) - 1; - if (x < 0 || x >= width || y < 0 || y >= height || --block < 0) {return} - if (world.getDot(x, y) === 0) { - world.setDot(x, y, Organism.getColor(color)); - } + if (x < 0 || x >= width || y < 0 || y >= height) {return} + if (world.isFree(x, y)) {world.setDot(x, y, Organism.getColor(color))} } } @@ -60,11 +58,11 @@ class Energy { const world = this._manager.world; const width = Config.worldWidth; const height = Config.worldHeight; - const orgs = this._manager.positions; + const poses = this._manager.positions; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - if (typeof orgs[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} + if (typeof poses[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 6e5dc36..08fc16d 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -132,25 +132,24 @@ class Organisms extends Configurable { } move(x1, y1, x2, y2, org) { - let moved = false; const world = this.world; if (world.isFree(x2, y2) === false) {return false} - if (x1 !== x2 || y1 !== y2) {moved = true; world.setDot(x1, y1, 0)} world.setDot(x2, y2, org.color); + if (x1 === x2 && y1 === y2) {return false} + world.setDot(x1, y1, 0); this.onAfterMove(x1, y1, x2, y2, org); - return moved; + return true; } createOrg(pos, parent = null) { if (pos === false) {return false} const orgs = this.organisms; orgs.add(null); - let last = orgs.last; - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, last, parent); + let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, orgs.last, parent); - last.val = org; + orgs.last.val = org; this.addOrgHandlers(org); this.move(-1, -1, pos.x, pos.y, org); this.parent.fire(EVENTS.BORN_ORGANISM, org); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 7363600..3db505c 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -133,16 +133,11 @@ class Organisms extends BaseOrganisms { * @param {Number} x2 End X position * @param {Number} y2 End Y position * @param {Organism} org Organism, which is moving - * @returns {Boolean} * @override */ onAfterMove(x1, y1, x2, y2, org) { - if (x1 !== x2 || y1 !== y2) { - this.positions[POSID(x1, y1)] = undefined; - this.positions[POSID(x2, y2)] = org; - } - - return true; + this.positions[POSID(x1, y1)] = undefined; + this.positions[POSID(x2, y2)] = org; } _onGetEnergy(x, y, ret) { @@ -174,7 +169,7 @@ class Organisms extends BaseOrganisms { } else { ret.ret = eat; this.world.setDot(x, y, (((-eat + .5) << 0) >>> 0) + this.world.getDot(x, y)); - this.parent.fire(EVENTS.PUT_ENERGY, eat); + this.parent.fire(EVENTS.PUT_ENERGY, -eat); } // // Organism found From 9108168b9ab37ca540d3742e7e0849f232716d00 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 27 Feb 2018 11:48:15 +0200 Subject: [PATCH 243/291] in process of fixing critical issue with unsynchronized organism positions and their world coordinates --- .../manager/plugins/organisms/Organisms.js | 32 ++++--------- .../plugins/organisms/dos/Operators.js | 20 +++----- .../plugins/organisms/dos/Organisms.js | 47 ++++--------------- 3 files changed, 23 insertions(+), 76 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 08fc16d..9bb7ee0 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -18,6 +18,8 @@ const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); const RAND_OFFS = 3; +const POSID = Helper.posId; + // TODO: inherit this class from Configurable class Organisms extends Configurable { /** @@ -29,19 +31,6 @@ class Organisms extends Configurable { */ compare(org1, org2) {} - /** - * Is called after moving of organism is done. Updates Manager.positions - * map with a new position of organism - * @param {Number} x1 Start X position - * @param {Number} y1 Start Y position - * @param {Number} x2 End X position - * @param {Number} y2 End Y position - * @param {Organism} org Organism, which is moving - * @returns {Boolean} - * @abstract - */ - onAfterMove(x1, y1, x2, y2, org) {} - /** * Is called before cloning of organism * @param {Organism} org @@ -57,13 +46,6 @@ class Organisms extends Configurable { */ onClone(org, child) {} - /** - * Is called after organism has killed - * @param {Organism} org Killed organism - * @abstract - */ - onAfterKillOrg(org) {} - /** * Creates one instance of organism. You have to override this * method in your child class @@ -133,12 +115,16 @@ class Organisms extends Configurable { move(x1, y1, x2, y2, org) { const world = this.world; - if (world.isFree(x2, y2) === false) {return false} + + org.x = x2; + org.y = y2; world.setDot(x2, y2, org.color); + if (x1 === x2 && y1 === y2) {return false} world.setDot(x1, y1, 0); - this.onAfterMove(x1, y1, x2, y2, org); + this.positions[POSID(x1, y1)] = undefined; + this.positions[POSID(x2, y2)] = org; return true; } @@ -261,7 +247,7 @@ class Organisms extends Configurable { } this.organisms.del(org.item); this.world.setDot(org.x, org.y, 0); - this.onAfterKillOrg(org); + this.positions[org.posId] = undefined; this.parent.fire(EVENTS.KILL, org); //Console.info(org.id, ' die'); } diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index eda9f89..c72feaf 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -209,10 +209,10 @@ class OperatorsDos extends Operators { onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} - onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y).x; return ++line} - onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y).x; return ++line} - onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1).y; return ++line} - onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1).y; return ++line} + onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y); return ++line} + onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y); return ++line} + onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1); return ++line} + onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1); return ++line} onFromMem(num, line, org) { if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { @@ -262,16 +262,8 @@ class OperatorsDos extends Operators { } _step(org, x1, y1, x2, y2) { - const ret = this._ret; - - ret.ret = 0; - this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2, ret); - if (ret.ret > 0) { - org.x = ret.x; - org.y = ret.y; - } - - return ret; + this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2); + return +(org.energy > 0); } /** diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 3db505c..c525068 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -116,30 +116,6 @@ class Organisms extends BaseOrganisms { return new Organism(...args); } - /** - * Is called after organism has killed - * @param {Organism} org Killed organism - * @override - */ - onAfterKillOrg(org) { - this.positions[org.posId] = undefined; - } - - /** - * Is called after moving of organism is done. Updates this.positions - * map with a new position of organism - * @param {Number} x1 Start X position - * @param {Number} y1 Start Y position - * @param {Number} x2 End X position - * @param {Number} y2 End Y position - * @param {Organism} org Organism, which is moving - * @override - */ - onAfterMove(x1, y1, x2, y2, org) { - this.positions[POSID(x1, y1)] = undefined; - this.positions[POSID(x2, y2)] = org; - } - _onGetEnergy(x, y, ret) { const posId = POSID(x, y); @@ -192,7 +168,7 @@ class Organisms extends BaseOrganisms { } } - _onStep(org, x1, y1, x2, y2, ret) { + _onStep(org, x1, y1, x2, y2) { if (org.energy < 1) {return} const man = this.parent; let dir; @@ -202,10 +178,7 @@ class Organisms extends BaseOrganisms { // Organism has moved, but still is within the current world (client) // if (dir === DIR.NO) { - ret.x = x2; - ret.y = y2; - ret.ret = +this.move(x1, y1, x2, y2, org); - return; + return this.move(x1, y1, x2, y2, org); } // // Current organism try to move out of the world. @@ -230,15 +203,10 @@ class Organisms extends BaseOrganisms { // In this case coordinates (x,y) should stay the same // if (man.isDistributed() || Config.worldCyclical === false) { - ret.x = x1; - ret.y = y1; - ret.ret = +this.move(x1, y1, x1, y1, org); - return; + return this.move(x1, y1, x1, y1, org); } - ret.x = x2; - ret.y = y2; - ret.ret = +this.move(x1, y1, x2, y2, org); + this.move(x1, y1, x2, y2, org); } _onCheckAt(x, y, ret) { @@ -265,13 +233,14 @@ class Organisms extends BaseOrganisms { if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { const org = this.organisms.last.val; org.unserialize(orgJson); + const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; // - // We have to update organism color and coordinates + // IMPORTANT: We have to update organism's coordinates // org.x = x; org.y = y; - const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; - (org.energy <= energy) && this.parent.fire(EVENTS.KILL_STEP_IN, org); + this.move(x, y, x, y, org); + org.energy <= energy && this.parent.fire(EVENTS.KILL_STEP_IN, org); org.energy -= energy; } } From 97b389bc54c0e8fc07738397c2b6efc49c2bbd90 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 28 Feb 2018 00:29:50 +0200 Subject: [PATCH 244/291] fixed critical issue with zombie organisms --- .../manager/plugins/organisms/Organisms.js | 21 +++++++++++-------- .../plugins/organisms/dos/Organisms.js | 13 ++++++------ client/src/view/World.js | 12 ++++++----- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 9bb7ee0..ccbf40a 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -102,7 +102,7 @@ class Organisms extends Configurable { } addOrgHandlers(org) { - org.on(ORG_EVENTS.DESTROY, this._onKillOrg.bind(this)); + org.on(ORG_EVENTS.DESTROY, this._onDestroyOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); org.on(ORG_EVENTS.KILL_AGE, this._onKillAgeOrg.bind(this)); org.on(ORG_EVENTS.ITERATION, this._onIterationOrg.bind(this)); @@ -129,15 +129,16 @@ class Organisms extends Configurable { return true; } - createOrg(pos, parent = null) { - if (pos === false) {return false} + createOrg(x, y, parent = null) { + if (x === -1) {return false} const orgs = this.organisms; orgs.add(null); - let org = this.createEmptyOrg(++this._orgId + '', pos.x, pos.y, orgs.last, parent); + let org = this.createEmptyOrg(++this._orgId + '', x, y, orgs.last, parent); orgs.last.val = org; this.addOrgHandlers(org); - this.move(-1, -1, pos.x, pos.y, org); + this.world.setDot(x, y, org.color); + this.positions[org.posId] = org; this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); @@ -200,8 +201,10 @@ class Organisms extends Configurable { _clone(org, isCrossover = false) { if (this.onBeforeClone(org) === false) {return false} - let pos = this.world.getNearFreePos(org.x, org.y); - if (pos === false || this.createOrg(pos, org) === false) {return false} + let x; + let y; + [x, y] = this.world.getNearFreePos(org.x, org.y); + if (x === -1 || this.createOrg(x, y, org) === false) {return false} let child = this.organisms.last.val; this.onClone(org, child); @@ -226,7 +229,7 @@ class Organisms extends Configurable { this.reset(); for (let i = 0, len = OConfig.orgStartAmount; i < len; i++) { - this.createOrg(world.getFreePos()); + this.createOrg(...world.getFreePos()); } Console.info('Population has created'); } @@ -239,7 +242,7 @@ class Organisms extends Configurable { return this.parent.organisms.size; } - _onKillOrg(org) { + _onDestroyOrg(org) { if (this.randOrgItem === org.item) { if ((this.randOrgItem = org.item.next) === null) { this.randOrgItem = this.organisms.first; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index c525068..0ce8319 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -139,7 +139,7 @@ class Organisms extends BaseOrganisms { // Energy found // if (typeof(positions[posId]) === 'undefined') { - if (eat > 0) { + if (eat >= 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); } else { @@ -202,10 +202,11 @@ class Organisms extends BaseOrganisms { // activated client on that side. So this is a border for him. // In this case coordinates (x,y) should stay the same // - if (man.isDistributed() || Config.worldCyclical === false) { - return this.move(x1, y1, x1, y1, org); - } - + if (man.isDistributed() || Config.worldCyclical === false) {return} + // + // The world is cyclical (worldCyclical). The organism will + // appear on the other side + // this.move(x1, y1, x2, y2, org); } @@ -239,7 +240,7 @@ class Organisms extends BaseOrganisms { // org.x = x; org.y = y; - this.move(x, y, x, y, org); + this.world.setDot(x, y, org.color); org.energy <= energy && this.parent.fire(EVENTS.KILL_STEP_IN, org); org.energy -= energy; } diff --git a/client/src/view/World.js b/client/src/view/World.js index 205e6f9..0c7e880 100644 --- a/client/src/view/World.js +++ b/client/src/view/World.js @@ -29,7 +29,7 @@ const WEVENTS = { * {Number} Amount of attempts for finding free place in a world. * The same like this.getDot(x, y) === 0 */ -const FREE_DOT_ATTEMPTS = 300; +const FREE_DOT_ATTEMPTS = 100; class World extends Observer { constructor (width, height) { @@ -86,7 +86,7 @@ class World extends Observer { while (this.getDot(x = rand(width), y = rand(height)) > 0 && i-- > 0) {} - return i > 0 ? {x, y} : false + return i > 0 ? [x, y] : [-1, -1] } getNearFreePos(x, y) { @@ -102,13 +102,15 @@ class World extends Observer { ]; for (let i = 0, j = 0; i < 8; i++) { - if (this.getDot(positions[j], positions[j + 1]) === 0 && x >= 0 && x < this._width && y >= 0 && y < this._height) { - return {x: positions[j], y: positions[j + 1]}; + x = positions[j]; + y = positions[j + 1]; + if (this.getDot(x, y) === 0 && x >= 0 && x < this._width && y >= 0 && y < this._height) { + return [positions[j], positions[j + 1]]; } j += 2; } - return false; + return [-1, -1]; } isFree(x, y) { From c4f0a7498051afde2e0a1b37ecac38f0204ca374 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 28 Feb 2018 22:01:44 +0200 Subject: [PATCH 245/291] small refactoring --- client/src/manager/plugins/organisms/dos/Operators.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index c72feaf..18b5124 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -86,7 +86,7 @@ class OperatorsDos extends Operators { /** * {Object} Reusable object to pass it as a parameter to this.fire(..., ret) */ - this._ret = {ret: 0, x: 0, y: 0}; + this._ret = {ret: 0}; // // We have to set amount of available operators for correct // working of mutations of operators. From e18cc3f89d2a5fe33136e82aa579fa34418ddece Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Mar 2018 00:07:51 +0200 Subject: [PATCH 246/291] fixed tests #83 --- .../plugins/organisms/dos/Operators.js | 12 +-- .../plugins/organisms/dos/OperatorsSpec.js | 84 +++++++------------ 2 files changed, 38 insertions(+), 58 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 18b5124..bd1752d 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -209,10 +209,10 @@ class OperatorsDos extends Operators { onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} - onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y); return ++line} - onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y); return ++line} - onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1); return ++line} - onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1); return ++line} + onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y, org.x - 1); return ++line} + onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y, org.x + 1); return ++line} + onStepUp(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y - 1, org.y - 1); return ++line} + onStepDown(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x, org.y + 1, org.y + 1); return ++line} onFromMem(num, line, org) { if (Num.getBits(num, this._BITS_AFTER_TWO_VARS, 1)) { @@ -261,9 +261,9 @@ class OperatorsDos extends Operators { return ret.ret; } - _step(org, x1, y1, x2, y2) { + _step(org, x1, y1, x2, y2, step) { this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2); - return +(org.energy > 0); + return org.x === x2 && org.y === y2 ? step : 0; } /** diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 3c45882..05d78b3 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -572,10 +572,9 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step left", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); }); expect(ops.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v0=stepLeft(); @@ -587,14 +586,11 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step left with no free space on the left", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = x1; - ret.y = y1; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); }); expect(ops.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v0=stepLeft(); - expect(ops.vars).toEqual([3,1,2,3]); + expect(ops.vars).toEqual([0,1,2,3]); expect(org.x).toBe(3); expect(org.y).toBe(4); }); @@ -606,10 +602,9 @@ describe("client/src/organism/OperatorsDos", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 2 && y2 === 4).toBe(true); }); expect(ops1.onStepLeft(0x0a1fffff, 0, org)).toEqual(1); // v1=stepLeft(); @@ -634,10 +629,9 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step right", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); }); expect(ops.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v0=stepRight(); @@ -649,14 +643,11 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step right with no free space on the right", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = x1; - ret.y = y1; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); }); expect(ops.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v0=stepRight(); - expect(ops.vars).toEqual([3,1,2,3]); + expect(ops.vars).toEqual([0,1,2,3]); expect(org.x).toBe(3); expect(org.y).toBe(4); }); @@ -668,10 +659,9 @@ describe("client/src/organism/OperatorsDos", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 4 && y2 === 4).toBe(true); }); expect(ops1.onStepRight(0x0a1fffff, 0, org)).toEqual(1); // v1=stepRight(); @@ -696,10 +686,9 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step up", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); }); expect(ops.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v0=stepUp(); @@ -711,14 +700,11 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step up with no free space on above", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = x1; - ret.y = y1; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); }); expect(ops.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v0=stepUp(); - expect(ops.vars).toEqual([4,1,2,3]); + expect(ops.vars).toEqual([0,1,2,3]); expect(org.x).toBe(3); expect(org.y).toBe(4); }); @@ -730,10 +716,9 @@ describe("client/src/organism/OperatorsDos", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 3).toBe(true); }); expect(ops1.onStepUp(0x0a1fffff, 0, org)).toEqual(1); // v1=stepUp(); @@ -758,10 +743,9 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step down", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); }); expect(ops.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v0=stepDown(); @@ -773,14 +757,11 @@ describe("client/src/organism/OperatorsDos", () => { it("Checking step down with no free space below", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 0; - ret.x = x1; - ret.y = y1; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); }); expect(ops.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v0=stepDown(); - expect(ops.vars).toEqual([4,1,2,3]); + expect(ops.vars).toEqual([0,1,2,3]); expect(org.x).toBe(3); expect(org.y).toBe(4); }); @@ -792,10 +773,9 @@ describe("client/src/organism/OperatorsDos", () => { org.x = 3; org.y = 4; - org.on(EVENTS.STEP, (org, x1, y1, x2, y2, ret) => { - ret.ret = 1; - ret.x = x2; - ret.y = y2; + org.on(EVENTS.STEP, (org, x1, y1, x2, y2) => { + org.x = x2; + org.y = y2; expect(x1 === 3 && y1 === 4 && x2 === 3 && y2 === 5).toBe(true); }); expect(ops1.onStepDown(0x0a1fffff, 0, org)).toEqual(1); // v1=stepDown(); From 6e128b29aacdc10aedb018d069850572e8cd0fc1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Mar 2018 20:38:19 +0200 Subject: [PATCH 247/291] added new test #83 --- .../plugins/organisms/dos/Operators.js | 14 +++++++++++- .../plugins/organisms/dos/OperatorsSpec.js | 22 +++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index bd1752d..2555461 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -169,7 +169,19 @@ class OperatorsDos extends Operators { } /** - * while(v0 op v1) goto offs + * Handler of 'while' operator. 'xx' means, that amount of bits depends on + * configuration. '...' means, that all other bits are + * ignored. Offset of closing bracket means row number after, which this + * bracket will be added. Offset of closing bracket is calculating using + * formula: line + offs. Example: + * bits : 8 xx xx 2 xx + * number: 00000011 00 01 00 00... + * desc : while v0 v1 < } + * string: while (v0 < v1) {} + * + * @param {Number} num One bit packed byte code row + * @param {Number} line Current line in DOS code + * @return {Number} Next line number to proceed */ onLoop(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 05d78b3..e356ace 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1314,7 +1314,7 @@ describe("client/src/organism/OperatorsDos", () => { '10 00 01 10 00000010 1111111111', '01 00 0000000000000010 111111', '10 00 01 10 00000010 1111111111', - '01 01 0000000000000001 111111', + '01 01 0000000000000001 111111' ]); org.vm.run(org); expect(org.vm.vars).toEqual([2,1,0,0]); @@ -1332,11 +1332,29 @@ describe("client/src/organism/OperatorsDos", () => { '10 00 01 10 00000010 1111111111', '10 00 01 10 00000001 1111111111', '01 00 0000000000000010 111111', - '01 01 0000000000000001 111111', + '01 01 0000000000000001 111111' ]); org.vm.run(org); expect(org.vm.vars).toEqual([2,1,0,0]); }); + + + /** + * while (v0 === v1) { // true + * v0 = 1 + * } + * v1 = 1 + */ + it('Checks if inside if with false condition', () => { + script([ + '11 00 01 10 00000001 1111111111', + '01 00 0000000000000001 111111', + '01 01 0000000000000001 111111' + ]); + OConfig.codeYieldPeriod = 4; + org.vm.run(org); + expect(org.vm.vars).toEqual([1,1,0,0]); + }); //const c2s = new C2S({api: {}}); //c2s.format(org.vm.code); }); From b6ecb788929c5a8bacadc65b4c91dbcda5a69f42 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Mar 2018 21:09:08 +0200 Subject: [PATCH 248/291] added new complex test #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index e356ace..86e3de9 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1251,7 +1251,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks if inside if with false condition outside', () => { script([ '10 00 01 11 00000010 1111111111', '10 00 01 10 00000001 1111111111', @@ -1270,7 +1270,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks if inside if with false condition outside 2', () => { script([ '10 00 01 11 00000011 1111111111', '10 00 01 10 00000010 1111111111', @@ -1291,7 +1291,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks if inside if with true condition and 3 assignments', () => { script([ '10 00 01 10 00000011 1111111111', '10 00 01 10 00000010 1111111111', @@ -1309,7 +1309,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks if inside if with var assign', () => { script([ '10 00 01 10 00000010 1111111111', '01 00 0000000000000010 111111', @@ -1327,7 +1327,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks if inside if with both true conditions', () => { script([ '10 00 01 10 00000010 1111111111', '10 00 01 10 00000001 1111111111', @@ -1345,7 +1345,7 @@ describe("client/src/organism/OperatorsDos", () => { * } * v1 = 1 */ - it('Checks if inside if with false condition', () => { + it('Checks while with true and then false conditions', () => { script([ '11 00 01 10 00000001 1111111111', '01 00 0000000000000001 111111', @@ -1355,6 +1355,56 @@ describe("client/src/organism/OperatorsDos", () => { org.vm.run(org); expect(org.vm.vars).toEqual([1,1,0,0]); }); + /** + * while (v0 !== v1) {} // false + * v0 = 1 + */ + it('Checks while with false condition', () => { + script([ + '11 00 01 11 00000000 1111111111', + '01 00 0000000000000001 111111' + ]); + org.vm.run(org); + expect(org.vm.vars).toEqual([1,0,0,0]); + }); + /** + * if (v0 === v1) { + * while (v0 === v1) { // true + * v0 = 1 + * } + * } + * v1 = 1 + */ + it('Checks while with if outside', () => { + script([ + '10 00 01 10 00000010 1111111111', + '11 00 01 10 00000001 1111111111', + '01 00 0000000000000001 111111', + '01 01 0000000000000001 111111' + ]); + OConfig.codeYieldPeriod = 5; + org.vm.run(org); + expect(org.vm.vars).toEqual([1,1,0,0]); + }); + /** + * while (v0 === v1) { + * while (v0 === v1) { // true + * v0 = 1 + * } + * } + * v1 = 1 + */ + it('Checks 2 whiles', () => { + script([ + '11 00 01 10 00000010 1111111111', + '11 00 01 10 00000001 1111111111', + '01 00 0000000000000001 111111', + '01 01 0000000000000001 111111' + ]); + OConfig.codeYieldPeriod = 6; + org.vm.run(org); + expect(org.vm.vars).toEqual([1,1,0,0]); + }); //const c2s = new C2S({api: {}}); //c2s.format(org.vm.code); }); From 3b8b9f7735e8d87be8ee5bbc44913a04202b15d1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Mar 2018 22:26:02 +0200 Subject: [PATCH 249/291] added new tests #83 --- .../plugins/organisms/dos/Operators.js | 1 + .../plugins/organisms/dos/OperatorsSpec.js | 32 +++++++++++++++++++ client/src/vm/Operators.js | 6 ++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 2555461..f7f36b6 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -101,6 +101,7 @@ class OperatorsDos extends Operators { destroy() { super.destroy(); this._OPERATORS_CB = null; + this._ret = null; } get operators() {return this._OPERATORS_CB} diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 86e3de9..3152a7a 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -13,6 +13,38 @@ describe("client/src/organism/OperatorsDos", () => { afterAll(() => OConfig.codeBitsPerVar = cbpv); + describe('Checks creation, destroy and public API', () => { + it('Checking instance creation', () => { + let offs = []; + let vars = []; + let obs = {}; + let ops = new OperatorsDos(offs, vars, obs); + expect(ops.offs).toBe(offs); + expect(ops.vars).toBe(vars); + expect(ops.obs).toBe(obs); + ops.destroy(); + }); + it('Checking destroy', () => { + let offs = []; + let vars = []; + let obs = {}; + let ops = new OperatorsDos(offs, vars, obs); + ops.destroy(); + expect(ops.offsets).not.toBe(offs); + expect(ops.vars).not.toBe(vars); + expect(ops.obs).not.toBe(obs); + }); + it('Checking operators getter', () => { + let offs = []; + let vars = []; + let obs = {}; + let ops = new OperatorsDos(offs, vars, obs); + expect(Array.isArray(ops.operators)).toBe(true); + expect(ops.operators.length > 0).toBe(true); + ops.destroy(); + }); + }); + describe('onVar() method', () => { let org; let ops; diff --git a/client/src/vm/Operators.js b/client/src/vm/Operators.js index b55b69f..ffff580 100644 --- a/client/src/vm/Operators.js +++ b/client/src/vm/Operators.js @@ -10,15 +10,15 @@ class Operators { * {Array} Array of offsets for closing braces. For 'for', 'if' * and other operators. */ - this.offs = offs; + this.offs = offs; /** * {Array} Available variables */ - this.vars = vars; + this.vars = vars; /** * {Observer} Observer for sending external events */ - this.obs = obs; + this.obs = obs; } destroy() { From 6ed915ec20e45892d6762d96c117580a68594d0b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 1 Mar 2018 23:42:49 +0200 Subject: [PATCH 250/291] added new tests #83 renamed Num.get() -> Num.rand() #85 --- .../src/manager/plugins/organisms/Mutator.js | 17 +-- .../plugins/organisms/dos/OperatorsSpec.js | 3 - client/src/vm/Num.js | 25 ++-- client/src/vm/NumSpec.js | 117 +++++++++++------- client/src/vm/VM.js | 4 +- client/src/vm/VMSpec.js | 29 +++-- 6 files changed, 107 insertions(+), 88 deletions(-) diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 20c8044..b7f7abe 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -19,7 +19,7 @@ const ADD_MUTAION_INDEX = 6; class Mutator { static _onChange(org) { const vm = org.vm; - vm.updateLine(Helper.rand(vm.size), Num.get()); + vm.updateLine(Helper.rand(vm.size), Num.rand()); org.changes += Num.MAX_BITS; } @@ -36,16 +36,17 @@ class Mutator { const rand = Helper.rand; const vm = org.vm; const index = rand(vm.size); - const rnd = rand(3); - + const rnd = rand(2); + // + // Toggles operator bits only + // if (rnd === 0) { vm.updateLine(index, Num.setOperator(vm.getLine(index), rand(vm.operators.operators.length))); - org.changes += Num.MAX_BITS; - } else if (rnd === 1) { - vm.updateLine(index, Num.setVar(vm.getLine(index), rand(Num.VARS), rand(Num.MAX_VAR))); - org.changes += Num.BITS_PER_VAR; + org.changes += Num.BITS_PER_OPERATOR; + // + // Toggles specified bit, except operator bits + // } else { - // toggle specified bit vm.updateLine(index, vm.getLine(index) ^ (1 << rand(Num.VAR_BITS_OFFS - 1))); org.changes++; } diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 3152a7a..14d5bb9 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -1,5 +1,4 @@ const _fill = require('lodash/fill'); -//const C2S = require('./Code2String'); describe("client/src/organism/OperatorsDos", () => { const OConfig = require('./../../organisms/Config'); @@ -1437,7 +1436,5 @@ describe("client/src/organism/OperatorsDos", () => { org.vm.run(org); expect(org.vm.vars).toEqual([1,1,0,0]); }); - //const c2s = new C2S({api: {}}); - //c2s.format(org.vm.code); }); }); \ No newline at end of file diff --git a/client/src/vm/Num.js b/client/src/vm/Num.js index 8f2f8dc..1a7c6a8 100644 --- a/client/src/vm/Num.js +++ b/client/src/vm/Num.js @@ -1,5 +1,5 @@ /** - * Class - helper for working with with byte code numbers + * Class - helper for working with byte code numbers * * @author flatline */ @@ -14,9 +14,8 @@ class Num { * script implementation */ static init(operatorAmount) { - this.setOperatorAmount(operatorAmount); - this.MAX_BITS = 32; + this.OPERATOR_AMOUNT = operatorAmount; this.BITS_PER_VAR = OConfig.codeBitsPerVar; this.BITS_PER_OPERATOR = OConfig.codeBitsPerOperator; this.NO_OPERATOR_MASK = 0xffffffff >>> this.BITS_PER_OPERATOR; @@ -31,24 +30,14 @@ class Num { this.BITS_OF_VAR3 = this.BITS_PER_OPERATOR + 3 * this.BITS_PER_VAR; } - static get VARS() {return (this.MAX_BITS - this.BITS_PER_OPERATOR) / this.BITS_PER_VAR} - - /** - * Sets amount of available operators for first bits - * @param {Number} amount - */ - static setOperatorAmount(amount) { - this._operatorsAmount = amount; - } - /** - * We have to use >>> 0 at the end, because << operator works - * with signed 32bit numbers, but not with unsigned like we need + * Returns random number for byte code. We have to use >>> 0 at + * the end, because << operator works with signed 32bit numbers, + * but not with unsigned like we need * @returns {number} */ - static get() { - const rand = Helper.rand; - return (rand(this._operatorsAmount) << (this.VAR_BITS_OFFS) | rand(this.NO_OPERATOR_MASK)) >>> 0; + static rand() { + return (Helper.rand(this.OPERATOR_AMOUNT) << (this.VAR_BITS_OFFS) | Helper.rand(this.NO_OPERATOR_MASK)) >>> 0; } static getOperator(num) { diff --git a/client/src/vm/NumSpec.js b/client/src/vm/NumSpec.js index 5b0a675..64e5dd3 100644 --- a/client/src/vm/NumSpec.js +++ b/client/src/vm/NumSpec.js @@ -1,61 +1,94 @@ +let Num = require('./Num'); +let OConfig = require('./../manager/plugins/organisms/Config'); + describe("client/src/organism/Num", () => { - let Num = require('./Num'); + const bpo = OConfig.codeBitsPerOperator; + const bpv = OConfig.codeBitsPerVar; - it("Checking getting random zero operator", () => { - Num.setOperatorAmount(0); - const n = Num.get() >>> 24; + beforeEach(() => {OConfig.codeBitsPerOperator = 8; OConfig.codeBitsPerVar = 2}); + afterEach( () => {OConfig.codeBitsPerOperator = bpo; OConfig.codeBitsPerVar = bpv}); - expect(n).toEqual(0); + describe('Checks initialization', () => { + it ('Checks init() method', () => { + Num.init(3); + expect(Num.OPERATOR_AMOUNT).toBe(3); + expect(Num.BITS_PER_VAR).toBe(OConfig.codeBitsPerVar); + expect(Num.BITS_PER_OPERATOR).toBe(OConfig.codeBitsPerOperator); + }); }); - it("Checking getting random operator (0..1)", () => { - Num.setOperatorAmount(1); - const n = Num.get() >>> 24; - expect(n === 0 || n === 1).toEqual(true); - }); - it("Checking getting random operator with probability", () => { - Num.setOperatorAmount(3); - let n; - - for (let i = 0; i < 10000; i++) { - n = Num.get() >>> 24; - expect(n >= 0 && n <= 2).toEqual(true); - } + describe('Checks rand() method', () => { + it('Checks if rand() generates a number', () => { + for (let i = 0; i < 10000; i++) { + const n = Num.rand(); + expect(typeof n).toBe('number'); + expect(n >= 0).toBe(true); + } + }); + it('Checks if rand() generates correct operator', () => { + for (let i = 0; i < 10000; i++) { + expect(Num.getOperator(Num.rand()) < Num.OPERATOR_AMOUNT).toBe(true); + } + }); }); - it('Checking getOperator() method', () => { - const n = 0xabffffff; + describe('Checks operator', () => { + it("Checking getting random zero operator", () => { + Num.init(0); + expect(Num.getOperator(Num.rand())).toEqual(0); + }); + it("Checking getting random operator (0..1)", () => { + Num.init(1); + const n = Num.getOperator(Num.rand()); + expect(n === 0 || n === 1).toEqual(true); + }); + it("Checking getting random operator with probability", () => { + Num.init(3); + let n; - expect(Num.getOperator(n)).toEqual(0xab); - }); + for (let i = 0; i < 10000; i++) { + n = Num.getOperator(Num.rand()); + expect(n >= 0 && n <= 2).toEqual(true); + } + }); + + it('Checking getOperator() method', () => { + const n = 0xabffffff; + Num.init(0xbb); + expect(Num.getOperator(n)).toEqual(0xab); + }); - it('Checking setOperator() method', () => { - const n = 0xabffffff; + it('Checking setOperator() method', () => { + const n = 0xabffffff; - expect(Num.setOperator(n, 0xbd)).toEqual(0xbdffffff); - expect(Num.setOperator(n, 0x00)).toEqual(0x00ffffff); - expect(Num.setOperator(n, 0x01)).toEqual(0x01ffffff); - expect(Num.setOperator(n, 0xff)).toEqual(0xffffffff); + Num.init(0xff); + expect(Num.setOperator(n, 0xbd)).toEqual(0xbdffffff); + expect(Num.setOperator(n, 0x00)).toEqual(0x00ffffff); + expect(Num.setOperator(n, 0x01)).toEqual(0x01ffffff); + expect(Num.setOperator(n, 0xff)).toEqual(0xffffffff); + }); }); - it('Checking getVar() method', () => { - let n = 0xabffffff; + describe('Checks getVar() method', () => { + it('Checking getVar() method', () => { + let n = 0xabffffff; - expect(Num.getVar(n, 0)).toEqual(3); - expect(Num.getVar(n, 1)).toEqual(3); - expect(Num.getVar(n, 3)).toEqual(3); + expect(Num.getVar(n, 0)).toEqual(3); + expect(Num.getVar(n, 1)).toEqual(3); + expect(Num.getVar(n, 3)).toEqual(3); - n = 0xbcbfffff; - expect(Num.getVar(n, 0)).toEqual(2); - expect(Num.getVar(n, 1)).toEqual(3); + n = 0xbcbfffff; + expect(Num.getVar(n, 0)).toEqual(2); + expect(Num.getVar(n, 1)).toEqual(3); - n = 0xbc9fffff; - expect(Num.getVar(n, 0)).toEqual(2); - expect(Num.getVar(n, 1)).toEqual(1); + n = 0xbc9fffff; + expect(Num.getVar(n, 0)).toEqual(2); + expect(Num.getVar(n, 1)).toEqual(1); - n = 0xbc00ffff; - expect(Num.getVar(n, 0)).toEqual(0); - expect(Num.getVar(n, 1)).toEqual(0); + n = 0xbc00ffff; + expect(Num.getVar(n, 0)).toEqual(0); + expect(Num.getVar(n, 1)).toEqual(0); + }); }); it('Checking setVar() method', () => { diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 1711d9b..6a56539 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -220,7 +220,7 @@ class VM extends Observer { * Inserts random generated number into the byte code at random position */ insertLine() { - this._code.splice(Helper.rand(this._code.length), 0, Num.get()); + this._code.splice(Helper.rand(this._code.length), 0, Num.rand()); this._reset(); } @@ -252,7 +252,7 @@ class VM extends Observer { const orgCode = this._code; size = pos + size; - while (pos < size) {orgCode[pos++] = Num.get()} + while (pos < size) {orgCode[pos++] = Num.rand()} this._reset(); } diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 6073706..5f6da98 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -3,7 +3,6 @@ describe("client/src/organism/VM", () => { const Observer = require('./../../../common/src/Observer'); const Helper = require('./../../../common/src/Helper'); const OConfig = require('./../manager/plugins/organisms/Config'); - const api = require('./../share/Config').api; const VM = require('./VM'); const Num = require('./Num'); const Operators = require('./Operators'); @@ -327,17 +326,17 @@ describe("client/src/organism/VM", () => { }); it('Checking insertLine() method 2', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - let get = Num.get; + const vm = new VM(() => {}, obs, () => {}); + let rand = Num.rand; - Num.get = () => 0xabcdefff; + Num.rand = () => 0xabcdefff; expect(vm.size).toEqual(0); vm.insertLine(); expect(vm.size).toEqual(1); expect(vm.code[0]).toEqual(0xabcdefff); - Num.get = get; + Num.rand = rand; vm.destroy(); }); @@ -351,7 +350,7 @@ describe("client/src/organism/VM", () => { vm.insertLine(); vm.insertLine(); vm.insertLine(); - Helper.rand = function (n) { + Helper.rand = function () { i++; if (i === 0) { // start return 1; @@ -382,7 +381,7 @@ describe("client/src/organism/VM", () => { vm.insertLine(); vm.insertLine(); vm.insertLine(); - Helper.rand = function (n) { + Helper.rand = function () { i++; if (i === 0) { // start return 1; @@ -413,7 +412,7 @@ describe("client/src/organism/VM", () => { vm.insertLine(); vm.insertLine(); vm.insertLine(); - Helper.rand = function (n) { + Helper.rand = function () { i++; if (i === 0) { // start return 1; @@ -450,10 +449,10 @@ describe("client/src/organism/VM", () => { it('Checking updateLine() method', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - let get = Num.get; + const vm = new VM(() => {}, obs, () => {}); + let rand = Num.rand; - Num.get = () => 0xabcdefff; + Num.rand = () => 0xabcdefff; vm.insertLine(); expect(vm.code[0]).toEqual(0xabcdefff); @@ -463,7 +462,7 @@ describe("client/src/organism/VM", () => { vm.updateLine(0, 0x12345678); expect(vm.code[0]).toEqual(0x12345678); - Num.get = get; + Num.rand = rand; vm.destroy(); }); @@ -494,9 +493,9 @@ describe("client/src/organism/VM", () => { it('Checking getLine()', () => { const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); - let get = Num.get; + let get = Num.rand; - Num.get = () => 0xabcdefff; + Num.rand = () => 0xabcdefff; expect(vm.size).toEqual(0); expect(vm.getLine(0)).toEqual(undefined); expect(vm.getLine(1)).toEqual(undefined); @@ -510,7 +509,7 @@ describe("client/src/organism/VM", () => { expect(vm.getLine(1)).toEqual(undefined); expect(vm.getLine(9)).toEqual(undefined); - Num.get = get; + Num.rand = get; vm.destroy(); }); }); \ No newline at end of file From 24a7d78c1eafd772632f0df9c9c778a06b5d9c04 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 2 Mar 2018 09:29:49 +0200 Subject: [PATCH 251/291] added new tests #83 --- client/src/vm/NumSpec.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/client/src/vm/NumSpec.js b/client/src/vm/NumSpec.js index 64e5dd3..ba83572 100644 --- a/client/src/vm/NumSpec.js +++ b/client/src/vm/NumSpec.js @@ -89,6 +89,25 @@ describe("client/src/organism/Num", () => { expect(Num.getVar(n, 0)).toEqual(0); expect(Num.getVar(n, 1)).toEqual(0); }); + it('Checking getVarX() methods', () => { + let n = 0xabffffff; + + expect(Num.getVar0(n)).toEqual(3); + expect(Num.getVar1(n)).toEqual(3); + expect(Num.getVar2(n)).toEqual(3); + + n = 0xbcbfffff; + expect(Num.getVar0(n)).toEqual(2); + expect(Num.getVar1(n)).toEqual(3); + + n = 0xbc9fffff; + expect(Num.getVar0(n)).toEqual(2); + expect(Num.getVar1(n)).toEqual(1); + + n = 0xbc00ffff; + expect(Num.getVar0(n)).toEqual(0); + expect(Num.getVar1(n)).toEqual(0); + }); }); it('Checking setVar() method', () => { From 0cb76a4508ccea6c544b90d36f9d1521c022ee6f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 2 Mar 2018 23:22:04 +0200 Subject: [PATCH 252/291] added new tests #83 --- client/src/vm/NumSpec.js | 44 ++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/client/src/vm/NumSpec.js b/client/src/vm/NumSpec.js index ba83572..5934658 100644 --- a/client/src/vm/NumSpec.js +++ b/client/src/vm/NumSpec.js @@ -71,6 +71,7 @@ describe("client/src/organism/Num", () => { describe('Checks getVar() method', () => { it('Checking getVar() method', () => { + Num.init(0xff); let n = 0xabffffff; expect(Num.getVar(n, 0)).toEqual(3); @@ -90,6 +91,7 @@ describe("client/src/organism/Num", () => { expect(Num.getVar(n, 1)).toEqual(0); }); it('Checking getVarX() methods', () => { + Num.init(0xff); let n = 0xabffffff; expect(Num.getVar0(n)).toEqual(3); @@ -103,27 +105,43 @@ describe("client/src/organism/Num", () => { n = 0xbc9fffff; expect(Num.getVar0(n)).toEqual(2); expect(Num.getVar1(n)).toEqual(1); + expect(Num.getVar2(n)).toEqual(3); + expect(Num.getVar3(n)).toEqual(3); n = 0xbc00ffff; expect(Num.getVar0(n)).toEqual(0); expect(Num.getVar1(n)).toEqual(0); + expect(Num.getVar2(n)).toEqual(0); + expect(Num.getVar3(n)).toEqual(0); + + n = 0x00000000; + expect(Num.getVar0(n)).toEqual(0); + expect(Num.getVar1(n)).toEqual(0); + expect(Num.getVar2(n)).toEqual(0); + expect(Num.getVar3(n)).toEqual(0); }); }); - it('Checking setVar() method', () => { - expect(Num.setVar(0xabffffff, 0, 2)).toEqual(0xabbfffff); - expect(Num.setVar(0xabffffff, 0, 3)).toEqual(0xabffffff); - expect(Num.setVar(0xabffffff, 0, 0)).toEqual(0xab3fffff); - expect(Num.setVar(0xabffffff, 2, 0)).toEqual(0xabf3ffff); - expect(Num.setVar(0xabffffff, 2, 2)).toEqual(0xabfbffff); + describe('Checks setVar() method', () => { + it('Checking setVar() method', () => { + Num.init(0xff); + expect(Num.setVar(0xabffffff, 0, 2)).toEqual(0xabbfffff); + expect(Num.setVar(0xabffffff, 0, 3)).toEqual(0xabffffff); + expect(Num.setVar(0xabffffff, 0, 0)).toEqual(0xab3fffff); + expect(Num.setVar(0xabffffff, 2, 0)).toEqual(0xabf3ffff); + expect(Num.setVar(0xabffffff, 2, 2)).toEqual(0xabfbffff); + }); }); - it('Checking getBits() method', () => { - expect(Num.getBits(0xabffffff, 0, 8)).toEqual(0xab); - expect(Num.getBits(0xabffffff, 0, 4)).toEqual(0xa); - expect(Num.getBits(0xabffffff, 4, 4)).toEqual(0xb); - expect(Num.getBits(0xabfbffff, 12, 2)).toEqual(0x2); - expect(Num.getBits(0xabcdffff, 8, 8)).toEqual(0xcd); - expect(Num.getBits(0xabcdffff, 16, 8)).toEqual(0xff); + describe('Checks getBits() method', () => { + it('Checking getBits() method', () => { + Num.init(0xff); + expect(Num.getBits(0xabffffff, 0, 8)).toEqual(0xab); + expect(Num.getBits(0xabffffff, 0, 4)).toEqual(0xa); + expect(Num.getBits(0xabffffff, 4, 4)).toEqual(0xb); + expect(Num.getBits(0xabfbffff, 12, 2)).toEqual(0x2); + expect(Num.getBits(0xabcdffff, 8, 8)).toEqual(0xcd); + expect(Num.getBits(0xabcdffff, 16, 8)).toEqual(0xff); + }); }); }); \ No newline at end of file From f8bb68dfbfa3281894cf13ee68d17cd774852597 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Mar 2018 00:14:24 +0200 Subject: [PATCH 253/291] added new tests #83 --- client/src/vm/VMSpec.js | 161 +++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 67 deletions(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 5f6da98..f797f7a 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -7,63 +7,71 @@ describe("client/src/organism/VM", () => { const Num = require('./Num'); const Operators = require('./Operators'); - it("Checking vm creation", () => { - let flag = false; - const obs = new Observer(1); - const vm = new VM(() => flag = true, obs, () => {}); - - vm.run(); - expect(flag).toEqual(false); - - vm.destroy(); - }); - - it("Checking parent argument and 'cloning' mode", () => { - const obs = new Observer(1); - const parent = new VM(() => {}, obs, () => {}); - - parent.insertLine(); - const vm = new VM(() => {}, obs, () => {}, parent); - - expect(vm.code[0] === parent.code[0]).toEqual(true); - expect(vm.size === parent.size).toEqual(true); - expect(vm.vars[0] === parent.vars[0]).toEqual(true); - - parent.destroy(); - vm.destroy(); - }); - - it("Checking 'vars' getter for non 'cloning' mode", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - - expect(vm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); - - vm.destroy(); - }); - - it("Checking no code size", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - - expect(vm.size).toEqual(0); - vm.run(); - expect(vm.size).toEqual(0); - - vm.destroy(); - }); - - it("Checking destroy", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - - vm.destroy(); - expect(vm.code).toEqual(null); + describe('Checking creation', () => { + it("Checking vm creation", () => { + let flag = false; + const obs = new Observer(1); + const vm = new VM(obs, () => flag = true, []); + + expect(flag).toEqual(true); + expect(vm.size).toEqual(0); + expect(vm.line).toEqual(0); + + obs.destroy(); + vm.destroy(); + }); + + it("Checking parent argument and 'cloning' mode", () => { + const obs = new Observer(1); + const parent = new VM(obs, () => {}, []); + + parent.insertLine(); + const vm = new VM(obs, () => {}, [], parent); + + expect(vm.code).toEqual(parent.code); + expect(vm.size).toEqual(parent.size); + expect(vm.vars).toEqual(parent.vars); + + obs.destroy(); + parent.destroy(); + vm.destroy(); + }); + + it("Checking 'vars' getter for non 'cloning' mode", () => { + const obs = new Observer(2); + const vm = new VM(obs, () => {}, []); + + expect(vm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); + + obs.destroy(); + vm.destroy(); + }); + + it("Checking no code size", () => { + const obs = new Observer(2); + const vm = new VM(obs, () => {}, []); + + expect(vm.size).toEqual(0); + vm.run(); + expect(vm.size).toEqual(0); + + obs.destroy(); + vm.destroy(); + }); + + it("Checking destroy", () => { + const obs = new Observer(2); + const vm = new VM(obs, () => {}, []); + + vm.destroy(); + expect(vm.code).toEqual(null); + obs.destroy(); + }); }); it("Checking 'code' and 'size' properties", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const obs = new Observer(2); + const vm = new VM(() => {}, obs, () => {}); expect(vm.code instanceof Array).toEqual(true); expect(vm.size).toEqual(0); @@ -80,6 +88,7 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); + obs.destroy(); }); it("Checking 'operators' property", () => { @@ -89,6 +98,7 @@ describe("client/src/organism/VM", () => { expect(vm.operators instanceof Operators).toEqual(true); vm.destroy(); + obs.destroy(); }); // it("Checking run method", () => { @@ -116,6 +126,7 @@ describe("client/src/organism/VM", () => { // api.set('codeOperatorsCls', coc); // // vm.destroy(); + // obs.destroy(); // }); it("Checking crossover with increasing child code", () => { @@ -158,6 +169,7 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it("Checking crossover with decreasing child code", () => { const obs = new Observer(1); @@ -197,6 +209,7 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it("Checking crossover with the same child code size", () => { const obs = new Observer(1); @@ -237,6 +250,7 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it("Checking crossover with no code size in parents", () => { const obs = new Observer(1); @@ -249,6 +263,7 @@ describe("client/src/organism/VM", () => { jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other", () => { const obs = new Observer(1); @@ -279,6 +294,7 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { const obs = new Observer(1); @@ -310,11 +326,12 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; jsvm1.destroy(); jsvm2.destroy(); + obs.destroy(); }); it('Checking insertLine() method', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const obs = new Observer(2); + const vm = new VM(() => {}, obs, () => {}); expect(vm.size).toEqual(0); vm.insertLine(); @@ -323,6 +340,7 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(2); vm.destroy(); + obs.destroy(); }); it('Checking insertLine() method 2', () => { const obs = new Observer(2); @@ -338,11 +356,12 @@ describe("client/src/organism/VM", () => { Num.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking copyLines() method', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -370,10 +389,11 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking copyLines() method 2', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -401,10 +421,11 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking copyLines() method 3', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -432,10 +453,11 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking copyLines() method with no code', () => { const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; Helper.rand = () => 0; @@ -445,6 +467,7 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking updateLine() method', () => { @@ -464,11 +487,12 @@ describe("client/src/organism/VM", () => { Num.rand = rand; vm.destroy(); + obs.destroy(); }); it('Checking removeLine() method', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const obs = new Observer(2); + const vm = new VM(() => {}, obs, () => {}); vm.insertLine(); expect(vm.size).toEqual(1); @@ -476,10 +500,11 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); + obs.destroy(); }); it('Checking removeLine() for empty code', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + const obs = new Observer(2); + const vm = new VM(() => {}, obs, () => {}); expect(vm.size).toEqual(0); vm.removeLine(); @@ -488,12 +513,13 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); + obs.destroy(); }); it('Checking getLine()', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - let get = Num.rand; + const obs = new Observer(2); + const vm = new VM(() => {}, obs, () => {}); + let get = Num.rand; Num.rand = () => 0xabcdefff; expect(vm.size).toEqual(0); @@ -511,5 +537,6 @@ describe("client/src/organism/VM", () => { Num.rand = get; vm.destroy(); + obs.destroy(); }); }); \ No newline at end of file From 92b915183c851e4801069dd0f138cd3650a84269 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Mar 2018 11:14:22 +0200 Subject: [PATCH 254/291] fixed more tests #83 small refactoring of VM.js --- client/src/vm/VM.js | 10 ++++---- client/src/vm/VMSpec.js | 51 ++++++++++++++++++++++------------------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 6a56539..a4eda0d 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -4,7 +4,6 @@ * TODO: explain here code one number format,... * * @author flatline - * TODO: may be this module is redundant * TODO: think about custom operators callbacks from outside. This is how * TODO: we may solve custom tasks */ @@ -40,6 +39,7 @@ class VM extends Observer { this._operatorCls = operatorCls; this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); this._code = parent && parent.code.slice() || []; + this._line = parent && parent.line || 0; /** * {Array} Array of two numbers. first - line number where we have * to return if first line appears. second - line number, where ends @@ -51,7 +51,6 @@ class VM extends Observer { */ this._operators = new operatorCls(this._offsets, this._vars, obs); this._ops = this._operators.operators; - this._line = 0; } get code() {return this._code} @@ -129,14 +128,15 @@ class VM extends Observer { } destroy() { + this._ops = null; this._operators.destroy && this._operators.destroy(); this._operators = null; - this._operatorCls = null; this._offsets = []; - this._vars = null; this._code = null; + this._vars = null; + this._operatorCls = null; + this._weights = null; this._obs = null; - this._ops = null; super.destroy(); } diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index f797f7a..6a2f948 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -7,7 +7,7 @@ describe("client/src/organism/VM", () => { const Num = require('./Num'); const Operators = require('./Operators'); - describe('Checking creation', () => { + describe('Checking creation and destroy', () => { it("Checking vm creation", () => { let flag = false; const obs = new Observer(1); @@ -31,6 +31,7 @@ describe("client/src/organism/VM", () => { expect(vm.code).toEqual(parent.code); expect(vm.size).toEqual(parent.size); expect(vm.vars).toEqual(parent.vars); + expect(vm.line).toEqual(parent.line); obs.destroy(); parent.destroy(); @@ -69,36 +70,38 @@ describe("client/src/organism/VM", () => { }); }); - it("Checking 'code' and 'size' properties", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + describe('Checking properties and getters', () => { + it("Checking 'code' and 'size' properties", () => { + const obs = new Observer(2); + const vm = new VM(obs, () => {}, []); - expect(vm.code instanceof Array).toEqual(true); - expect(vm.size).toEqual(0); + expect(vm.code instanceof Array).toEqual(true); + expect(vm.size).toEqual(0); - vm.insertLine(); - expect(vm.code instanceof Array).toEqual(true); - expect(vm.size).toEqual(1); + vm.insertLine(); + expect(vm.code instanceof Array).toEqual(true); + expect(vm.size).toEqual(1); - vm.insertLine(); - expect(vm.size).toEqual(2); - vm.removeLine(); - expect(vm.size).toEqual(1); - vm.removeLine(); - expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(2); + vm.removeLine(); + expect(vm.size).toEqual(1); + vm.removeLine(); + expect(vm.size).toEqual(0); - vm.destroy(); - obs.destroy(); - }); + vm.destroy(); + obs.destroy(); + }); - it("Checking 'operators' property", () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, Operators); + it("Checking 'operators' property", () => { + const obs = new Observer(2); + const vm = new VM(obs, Operators, []); - expect(vm.operators instanceof Operators).toEqual(true); + expect(vm.operators instanceof Operators).toEqual(true); - vm.destroy(); - obs.destroy(); + vm.destroy(); + obs.destroy(); + }); }); // it("Checking run method", () => { From fc404d8d8287ccad06049d5c65cfc27e4dbfc535 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Mar 2018 12:08:34 +0200 Subject: [PATCH 255/291] fixed/added more tests #83 --- client/src/vm/VM.js | 5 ++++- client/src/vm/VMSpec.js | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index a4eda0d..36ee4d6 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -61,9 +61,12 @@ class VM extends Observer { serialize() { return { + // 'obs' field will be added after deserialization + // 'operatorsCls' field will be added after deserialization + // 'operators' field will be added after deserialization + // 'weights' field will be added after deserialization offsets: this._offsets.slice(), vars : this._vars.slice(), - // 'operators' field will be added after insertion code : this._code.slice(), line : this._line }; diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 6a2f948..fa075a6 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -94,8 +94,8 @@ describe("client/src/organism/VM", () => { }); it("Checking 'operators' property", () => { - const obs = new Observer(2); - const vm = new VM(obs, Operators, []); + const obs = new Observer(2); + const vm = new VM(obs, Operators, []); expect(vm.operators instanceof Operators).toEqual(true); @@ -104,6 +104,40 @@ describe("client/src/organism/VM", () => { }); }); + describe('Checking serialization/deserialization', () => { + it('Checks serialization', () => { + const obs = new Observer(1); + const vm = new VM(obs, () => {}, []); + + vm.vars.splice(0, vm.vars.length, ...[0,1,2,3]); + expect(vm.serialize()).toEqual({ + offsets: [0], + vars : [0,1,2,3], + code : [], + line : 0 + }); + + vm.destroy(); + obs.destroy(); + }); + it('Checks serialization 2', () => { + const obs = new Observer(1); + const vm = new VM(obs, () => {}, []); + + vm.vars.splice(0, vm.vars.length, ...[4,3,2,1]); + vm.insertLine(); + expect(vm.serialize()).toEqual({ + offsets: [1], + vars : [4,3,2,1], + code : [vm.code[0]], + line : 0 + }); + + vm.destroy(); + obs.destroy(); + }); + }); + // it("Checking run method", () => { // let flag = ''; // class Ops extends Operators { From d5d2f2a3afad3964a14ab212fe82632d1b79ea70 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Mar 2018 15:23:22 +0200 Subject: [PATCH 256/291] fixed more tests #83 --- client/src/vm/VM.js | 4 ++-- client/src/vm/VMSpec.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 36ee4d6..77743fb 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -146,7 +146,7 @@ class VM extends Observer { /** * Does crossover between two parent byte codes. Takes second vm's code part - * (from start1 to end1 offset) and inserts it instead first vm code part (start...end). + * (from start1 to end1 offset) and inserts it into first vm code part (start...end). * For example: * code1 : [1,2,3] * code2 : [4,5,6] @@ -154,7 +154,7 @@ class VM extends Observer { * end : 2 * start1: 0 * end1 : 2 - * jsvm1.crossover(jsvm2) // [4,5,6] instead [2,3] ->, jsvm1 === [1,4,5,6] + * vm1.crossover(vm2) // [4,5,6] instead [2,3] ->, vm1 === [1,4,5,6] * * @param {VM} vm VM instance, from where we have to cut code part * @returns {Number} Amount of changes in current (this) vm diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index fa075a6..b417eaa 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -136,6 +136,43 @@ describe("client/src/organism/VM", () => { vm.destroy(); obs.destroy(); }); + + it('Checks deserialization', () => { + const obs = new Observer(1); + const vm = new VM(obs, Operators, []); + + vm.unserialize({ + offsets: [0], + vars : [0,1,2,3], + code : [], + line : 1 + }); + expect(vm.operators.offs).toEqual([0]); + expect(vm.vars).toEqual([0,1,2,3]); + expect(vm.code).toEqual([]); + expect(vm.line).toEqual(1); + + vm.destroy(); + obs.destroy(); + }); + it('Checks deserialization 2', () => { + const obs = new Observer(1); + const vm = new VM(obs, Operators, []); + + vm.unserialize({ + offsets: [3], + vars : [4,1,2,3], + code : [0xaabbccdd], + line : 0 + }); + expect(vm.operators.offs).toEqual([3]); + expect(vm.vars).toEqual([4,1,2,3]); + expect(vm.code).toEqual([0xaabbccdd]); + expect(vm.line).toEqual(0); + + vm.destroy(); + obs.destroy(); + }); }); // it("Checking run method", () => { From 77f98b5d36d13671edc3a4250590b27cdb48808a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 3 Mar 2018 15:41:56 +0200 Subject: [PATCH 257/291] fixed more tests #83 --- client/src/vm/VMSpec.js | 518 ++++++++++++++++++---------------------- 1 file changed, 229 insertions(+), 289 deletions(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index b417eaa..abda1de 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,28 +1,30 @@ describe("client/src/organism/VM", () => { - const eq = require('lodash/isEqual'); - const Observer = require('./../../../common/src/Observer'); - const Helper = require('./../../../common/src/Helper'); - const OConfig = require('./../manager/plugins/organisms/Config'); - const VM = require('./VM'); - const Num = require('./Num'); - const Operators = require('./Operators'); + const eq = require('lodash/isEqual'); + const Observer = require('./../../../common/src/Observer'); + const OrganismDos = require('./../manager/plugins/organisms/dos/Organism'); + const Helper = require('./../../../common/src/Helper'); + const OConfig = require('./../manager/plugins/organisms/Config'); + const VM = require('./VM'); + const Num = require('./Num'); + const Operators = require('./Operators'); + let obs; + + beforeEach(() => obs = new Observer(10)); + afterEach (() => obs.destroy()); describe('Checking creation and destroy', () => { it("Checking vm creation", () => { let flag = false; - const obs = new Observer(1); const vm = new VM(obs, () => flag = true, []); expect(flag).toEqual(true); expect(vm.size).toEqual(0); expect(vm.line).toEqual(0); - obs.destroy(); vm.destroy(); }); it("Checking parent argument and 'cloning' mode", () => { - const obs = new Observer(1); const parent = new VM(obs, () => {}, []); parent.insertLine(); @@ -33,46 +35,38 @@ describe("client/src/organism/VM", () => { expect(vm.vars).toEqual(parent.vars); expect(vm.line).toEqual(parent.line); - obs.destroy(); parent.destroy(); vm.destroy(); }); it("Checking 'vars' getter for non 'cloning' mode", () => { - const obs = new Observer(2); const vm = new VM(obs, () => {}, []); expect(vm.vars.length === Math.pow(2, OConfig.codeBitsPerVar)).toEqual(true); - obs.destroy(); vm.destroy(); }); it("Checking no code size", () => { - const obs = new Observer(2); const vm = new VM(obs, () => {}, []); expect(vm.size).toEqual(0); vm.run(); expect(vm.size).toEqual(0); - obs.destroy(); vm.destroy(); }); it("Checking destroy", () => { - const obs = new Observer(2); const vm = new VM(obs, () => {}, []); vm.destroy(); expect(vm.code).toEqual(null); - obs.destroy(); }); }); describe('Checking properties and getters', () => { it("Checking 'code' and 'size' properties", () => { - const obs = new Observer(2); const vm = new VM(obs, () => {}, []); expect(vm.code instanceof Array).toEqual(true); @@ -90,23 +84,19 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); - obs.destroy(); }); it("Checking 'operators' property", () => { - const obs = new Observer(2); const vm = new VM(obs, Operators, []); expect(vm.operators instanceof Operators).toEqual(true); vm.destroy(); - obs.destroy(); }); }); describe('Checking serialization/deserialization', () => { it('Checks serialization', () => { - const obs = new Observer(1); const vm = new VM(obs, () => {}, []); vm.vars.splice(0, vm.vars.length, ...[0,1,2,3]); @@ -118,10 +108,8 @@ describe("client/src/organism/VM", () => { }); vm.destroy(); - obs.destroy(); }); it('Checks serialization 2', () => { - const obs = new Observer(1); const vm = new VM(obs, () => {}, []); vm.vars.splice(0, vm.vars.length, ...[4,3,2,1]); @@ -134,11 +122,9 @@ describe("client/src/organism/VM", () => { }); vm.destroy(); - obs.destroy(); }); it('Checks deserialization', () => { - const obs = new Observer(1); const vm = new VM(obs, Operators, []); vm.unserialize({ @@ -153,10 +139,8 @@ describe("client/src/organism/VM", () => { expect(vm.line).toEqual(1); vm.destroy(); - obs.destroy(); }); it('Checks deserialization 2', () => { - const obs = new Observer(1); const vm = new VM(obs, Operators, []); vm.unserialize({ @@ -171,270 +155,241 @@ describe("client/src/organism/VM", () => { expect(vm.line).toEqual(0); vm.destroy(); - obs.destroy(); }); }); - // it("Checking run method", () => { - // let flag = ''; - // class Ops extends Operators { - // get operators() {return {1: (n,l)=>{flag=n+''+l;return l+1}}} - // get size () {return 1} - // } - // const obs = new Observer(1); - // const vm = new VM(() => {}, obs, () => {}); - // const coc = api.get('codeOperatorsCls'); - // const yp = api.get('codeYieldPeriod'); - // const fc = api.get('codeFitnessCls'); - // // - // // Small hack. Use of private field for this test only - // // - // vm._code.push(0b1000000000000000000000000); - // api.set('codeYieldPeriod', 1); - // api.set('codeFitnessCls', null); - // api.set('codeOperatorsCls', ''); - // vm.run({alive: true}); - // expect(flag === '167772160').toEqual(true); - // api.set('codeYieldPeriod', yp); - // api.set('codeFitnessCls', fc); - // api.set('codeOperatorsCls', coc); - // - // vm.destroy(); - // obs.destroy(); - // }); - - it("Checking crossover with increasing child code", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; - - Helper.rand = () => { - i++; - if (i === 0) {return 1} - if (i === 1) {return 2} - if (i === 2) {return 1} - if (i === 3) {return 3} - }; - - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); - - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); - - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 17000001, - 17000002, - 17000003, - 16000003, - 16000004 - ])).toEqual(true); - - Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); - }); - it("Checking crossover with decreasing child code", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; - - Helper.rand = () => { - i++; - if (i === 0) {return 1} - if (i === 1) {return 2} - if (i === 2) {return 1} - if (i === 3) {return 1} - }; - - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); - - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); - - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 17000001, - 16000003, - 16000004 - ])).toEqual(true); - - Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); - }); - it("Checking crossover with the same child code size", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; - - Helper.rand = () => { - i++; - if (i === 0) {return 1} - if (i === 1) {return 3} - if (i === 2) {return 1} - if (i === 3) {return 3} - }; - - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); - - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); - - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 17000001, - 17000002, - 17000003, - 16000004 - ])).toEqual(true); - - Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); - }); - it("Checking crossover with no code size in parents", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - - jsvm1.crossover(jsvm2); - expect(jsvm1.size).toEqual(0); - expect(jsvm2.size).toEqual(0); - - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); - }); - it("Checking crossover with no code size for one parent and twp lines of code for other", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; - - Helper.rand = () => { - i++; - if (i === 0) {return 0} - if (i === 1) {return 0} - if (i === 2) {return 1} - if (i === 3) {return 2} - }; - - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); + describe('run() method', () => { + it('Shouldn\'t work if code size is 0', () => { + const vm = new VM(obs, Operators, []); + const org = new OrganismDos('0', 0, 0, {}); + const energy = org.energy; - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 17000001, - 17000002 - ])).toEqual(true); + vm.run(org); + expect(vm.line).toEqual(0); + expect(org.energy).toEqual(energy); - Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); + org.destroy(); + vm.destroy(); + }); }); - it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { - const obs = new Observer(1); - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; - - Helper.rand = () => { - i++; - if (i === 0) {return 1} - if (i === 1) {return 2} - if (i === 2) {return 0} - if (i === 3) {return 0} - }; - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); + describe('Crossover', () => { + it("Checking crossover with increasing child code", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); + const rand = Helper.rand; + let i = -1; + + Helper.rand = () => { + i++; + if (i === 0) {return 1} + if (i === 1) {return 2} + if (i === 2) {return 1} + if (i === 3) {return 3} + }; + + jsvm1._code.push(16000000); + jsvm1._code.push(16000001); + jsvm1._code.push(16000002); + jsvm1._code.push(16000003); + jsvm1._code.push(16000004); + + jsvm2._code.push(17000000); + jsvm2._code.push(17000001); + jsvm2._code.push(17000002); + jsvm2._code.push(17000003); + jsvm2._code.push(17000004); + + jsvm1.crossover(jsvm2); + expect(eq(jsvm1.code, [ + 16000000, + 17000001, + 17000002, + 17000003, + 16000003, + 16000004 + ])).toEqual(true); + + Helper.rand = rand; + jsvm1.destroy(); + jsvm2.destroy(); + }); + it("Checking crossover with decreasing child code", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); + const rand = Helper.rand; + let i = -1; + + Helper.rand = () => { + i++; + if (i === 0) {return 1} + if (i === 1) {return 2} + if (i === 2) {return 1} + if (i === 3) {return 1} + }; + + jsvm1._code.push(16000000); + jsvm1._code.push(16000001); + jsvm1._code.push(16000002); + jsvm1._code.push(16000003); + jsvm1._code.push(16000004); + + jsvm2._code.push(17000000); + jsvm2._code.push(17000001); + jsvm2._code.push(17000002); + jsvm2._code.push(17000003); + jsvm2._code.push(17000004); + + jsvm1.crossover(jsvm2); + expect(eq(jsvm1.code, [ + 16000000, + 17000001, + 16000003, + 16000004 + ])).toEqual(true); + + Helper.rand = rand; + jsvm1.destroy(); + jsvm2.destroy(); + }); + it("Checking crossover with the same child code size", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); + const rand = Helper.rand; + let i = -1; + + Helper.rand = () => { + i++; + if (i === 0) {return 1} + if (i === 1) {return 3} + if (i === 2) {return 1} + if (i === 3) {return 3} + }; + + jsvm1._code.push(16000000); + jsvm1._code.push(16000001); + jsvm1._code.push(16000002); + jsvm1._code.push(16000003); + jsvm1._code.push(16000004); + + jsvm2._code.push(17000000); + jsvm2._code.push(17000001); + jsvm2._code.push(17000002); + jsvm2._code.push(17000003); + jsvm2._code.push(17000004); + + jsvm1.crossover(jsvm2); + expect(eq(jsvm1.code, [ + 16000000, + 17000001, + 17000002, + 17000003, + 16000004 + ])).toEqual(true); + + Helper.rand = rand; + jsvm1.destroy(); + jsvm2.destroy(); + }); + it("Checking crossover with no code size in parents", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 16000003, - ])).toEqual(true); - expect(jsvm2.size).toEqual(0); + jsvm1.crossover(jsvm2); + expect(jsvm1.size).toEqual(0); + expect(jsvm2.size).toEqual(0); - Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); - obs.destroy(); - }); + jsvm1.destroy(); + jsvm2.destroy(); + }); + it("Checking crossover with no code size for one parent and twp lines of code for other", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); + const rand = Helper.rand; + let i = -1; + + Helper.rand = () => { + i++; + if (i === 0) {return 0} + if (i === 1) {return 0} + if (i === 2) {return 1} + if (i === 3) {return 2} + }; + + jsvm2._code.push(17000000); + jsvm2._code.push(17000001); + jsvm2._code.push(17000002); + jsvm2._code.push(17000003); + + jsvm1.crossover(jsvm2); + expect(eq(jsvm1.code, [ + 17000001, + 17000002 + ])).toEqual(true); + + Helper.rand = rand; + jsvm1.destroy(); + jsvm2.destroy(); + }); + it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { + const jsvm1 = new VM(() => {}, obs, () => {}); + const jsvm2 = new VM(() => {}, obs, () => {}); + const rand = Helper.rand; + let i = -1; + + Helper.rand = () => { + i++; + if (i === 0) {return 1} + if (i === 1) {return 2} + if (i === 2) {return 0} + if (i === 3) {return 0} + }; + + jsvm1._code.push(16000000); + jsvm1._code.push(16000001); + jsvm1._code.push(16000002); + jsvm1._code.push(16000003); + + jsvm1.crossover(jsvm2); + expect(eq(jsvm1.code, [ + 16000000, + 16000003, + ])).toEqual(true); + expect(jsvm2.size).toEqual(0); + + Helper.rand = rand; + jsvm1.destroy(); + jsvm2.destroy(); + }); - it('Checking insertLine() method', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); + it('Checking insertLine() method', () => { + const vm = new VM(() => {}, obs, () => {}); - expect(vm.size).toEqual(0); - vm.insertLine(); - expect(vm.size).toEqual(1); - vm.insertLine(); - expect(vm.size).toEqual(2); + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + vm.insertLine(); + expect(vm.size).toEqual(2); - vm.destroy(); - obs.destroy(); - }); - it('Checking insertLine() method 2', () => { - const obs = new Observer(2); - const vm = new VM(() => {}, obs, () => {}); - let rand = Num.rand; + vm.destroy(); + }); + it('Checking insertLine() method 2', () => { + const vm = new VM(() => {}, obs, () => {}); + let rand = Num.rand; - Num.rand = () => 0xabcdefff; - expect(vm.size).toEqual(0); - vm.insertLine(); - expect(vm.size).toEqual(1); + Num.rand = () => 0xabcdefff; + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); - expect(vm.code[0]).toEqual(0xabcdefff); + expect(vm.code[0]).toEqual(0xabcdefff); - Num.rand = rand; - vm.destroy(); - obs.destroy(); + Num.rand = rand; + vm.destroy(); + }); }); it('Checking copyLines() method', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -463,10 +418,8 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); - obs.destroy(); }); it('Checking copyLines() method 2', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -495,10 +448,8 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); - obs.destroy(); }); it('Checking copyLines() method 3', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; let i = -1; @@ -527,10 +478,8 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); - obs.destroy(); }); it('Checking copyLines() method with no code', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let rand = Helper.rand; @@ -541,11 +490,9 @@ describe("client/src/organism/VM", () => { Helper.rand = rand; vm.destroy(); - obs.destroy(); }); it('Checking updateLine() method', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let rand = Num.rand; @@ -561,11 +508,9 @@ describe("client/src/organism/VM", () => { Num.rand = rand; vm.destroy(); - obs.destroy(); }); it('Checking removeLine() method', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); vm.insertLine(); @@ -574,10 +519,8 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); - obs.destroy(); }); it('Checking removeLine() for empty code', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); expect(vm.size).toEqual(0); @@ -587,11 +530,9 @@ describe("client/src/organism/VM", () => { expect(vm.size).toEqual(0); vm.destroy(); - obs.destroy(); }); it('Checking getLine()', () => { - const obs = new Observer(2); const vm = new VM(() => {}, obs, () => {}); let get = Num.rand; @@ -611,6 +552,5 @@ describe("client/src/organism/VM", () => { Num.rand = get; vm.destroy(); - obs.destroy(); }); }); \ No newline at end of file From 211e0504fdedf4f74f82860c0feb851aac463dd5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 10:51:57 +0200 Subject: [PATCH 258/291] fixed more tests #83 --- client/src/vm/VMSpec.js | 48 ++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index abda1de..8e70717 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,12 +1,13 @@ describe("client/src/organism/VM", () => { - const eq = require('lodash/isEqual'); - const Observer = require('./../../../common/src/Observer'); - const OrganismDos = require('./../manager/plugins/organisms/dos/Organism'); - const Helper = require('./../../../common/src/Helper'); - const OConfig = require('./../manager/plugins/organisms/Config'); - const VM = require('./VM'); - const Num = require('./Num'); - const Operators = require('./Operators'); + const eq = require('lodash/isEqual'); + const Observer = require('./../../../common/src/Observer'); + const OrganismDos = require('./../manager/plugins/organisms/dos/Organism'); + const Helper = require('./../../../common/src/Helper'); + const OConfig = require('./../manager/plugins/organisms/Config'); + const VM = require('./VM'); + const Num = require('./Num'); + const Operators = require('./Operators'); + const OperatorsDos = require('./../manager/plugins/organisms/dos/Operators'); let obs; beforeEach(() => obs = new Observer(10)); @@ -171,6 +172,37 @@ describe("client/src/organism/VM", () => { org.destroy(); vm.destroy(); }); + it('Shouldn\'t work if no energy', () => { + const vm = new VM(obs, Operators, []); + const org = new OrganismDos('0', 0, 0, {}); + const energy = -1; + + org.energy = energy; + vm.insertLine(); + vm.run(org); + expect(vm.line).toEqual(0); + expect(org.energy).toEqual(energy); + + org.destroy(); + vm.destroy(); + }); + it('Should run correct operator callbacks', () => { + const period = OConfig.codeYieldPeriod; + OConfig.codeYieldPeriod = 1; + const vm = new VM(obs, OperatorsDos, []); + const org = new OrganismDos('0', 0, 0, {}); + let flag = false; + + vm.insertLine(); + vm.updateLine(0, 0x00100000); + vm.operators.operators[0] = () => flag = true; + vm.run(org); + expect(flag).toEqual(true); + + org.destroy(); + vm.destroy(); + OConfig.codeYieldPeriod = period; + }); }); describe('Crossover', () => { From e941322de1127f1a0973474f1b80ced294ca0d5c Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 11:18:51 +0200 Subject: [PATCH 259/291] fixed more tests #83 --- client/src/vm/VMSpec.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 8e70717..d6bfa28 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -194,11 +194,28 @@ describe("client/src/organism/VM", () => { let flag = false; vm.insertLine(); - vm.updateLine(0, 0x00100000); + vm.updateLine(0, 0x00000000); vm.operators.operators[0] = () => flag = true; vm.run(org); expect(flag).toEqual(true); + org.destroy(); + vm.destroy(); + OConfig.codeYieldPeriod = period; + }); + it('Should run the same amount as codeYieldPeriod', () => { + const period = OConfig.codeYieldPeriod; + OConfig.codeYieldPeriod = 3; + const vm = new VM(obs, OperatorsDos, OConfig.orgOperatorWeights); + const org = new OrganismDos('0', 0, 0, {}); + let flag = 0; + + vm.insertLine(); + vm.updateLine(0, 0x00000000); + vm.operators.operators[0] = () => {flag++; return 1}; + vm.run(org); + expect(flag).toEqual(3); + org.destroy(); vm.destroy(); OConfig.codeYieldPeriod = period; From 10af5bce9738705dfb5b975143ef5ab2798f6599 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 12:25:52 +0200 Subject: [PATCH 260/291] fixed more tests #83 --- client/src/vm/VMSpec.js | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index d6bfa28..a9e98d2 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -206,9 +206,9 @@ describe("client/src/organism/VM", () => { it('Should run the same amount as codeYieldPeriod', () => { const period = OConfig.codeYieldPeriod; OConfig.codeYieldPeriod = 3; - const vm = new VM(obs, OperatorsDos, OConfig.orgOperatorWeights); - const org = new OrganismDos('0', 0, 0, {}); - let flag = 0; + const vm = new VM(obs, OperatorsDos, OConfig.orgOperatorWeights); + const org = new OrganismDos('0', 0, 0, {}); + let flag = 0; vm.insertLine(); vm.updateLine(0, 0x00000000); @@ -220,6 +220,32 @@ describe("client/src/organism/VM", () => { vm.destroy(); OConfig.codeYieldPeriod = period; }); + it('Should decrease energy', () => { + const alive = OConfig.orgAlivePeriod; + const period = OConfig.codeYieldPeriod; + const energy = OConfig.orgStartEnergy; + const weights = OConfig.orgOperatorWeights.slice(); + const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); + OConfig.codeYieldPeriod = 1; + OConfig.orgStartEnergy = 100; + OConfig.orgAlivePeriod = 100; + const vm = new VM(obs, OperatorsDos, OConfig.orgOperatorWeights); + const org = new OrganismDos('0', 0, 0, {}); + + vm.insertLine(); + vm.updateLine(0, 0x00000000); + expect(org.energy).toEqual(100); + vm.run(org); + expect(org.energy).toEqual(90); // 100 - (100 * .1 + 0) = 90 + + org.destroy(); + vm.destroy(); + OConfig.orgStartEnergy = energy; + OConfig.codeYieldPeriod = period; + OConfig.orgAlivePeriod = alive; + OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); + }); }); describe('Crossover', () => { From 96664cfc2417636803aff0253269c0f8f53c6010 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 14:42:38 +0200 Subject: [PATCH 261/291] fixed more tests #83 --- .../plugins/organisms/dos/OperatorsSpec.js | 6 +- client/src/vm/VMSpec.js | 193 +++++++++--------- common/tests/Helper.js | 15 +- 3 files changed, 107 insertions(+), 107 deletions(-) diff --git a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js index 14d5bb9..16da5a2 100644 --- a/client/src/manager/plugins/organisms/dos/OperatorsSpec.js +++ b/client/src/manager/plugins/organisms/dos/OperatorsSpec.js @@ -2,6 +2,7 @@ const _fill = require('lodash/fill'); describe("client/src/organism/OperatorsDos", () => { const OConfig = require('./../../organisms/Config'); + const THelper = require('./../../../../../../common/tests/Helper'); const cbpv = OConfig.codeBitsPerVar; OConfig.codeBitsPerVar = 2; const OperatorsDos = require('./Operators'); @@ -1202,9 +1203,8 @@ describe("client/src/organism/OperatorsDos", () => { const weights = OConfig.orgOperatorWeights.slice(); let ocfg; let org; - const script = code => { - for (let i = 0; i < code.length; i++) {org.vm.insertLine()} - for (let i = 0; i < code.length; i++) {org.vm.updateLine(i, typeof code[i] === 'string' ? parseInt(code[i].split(' ').join(''), 2) : code[i])} + const script = (code) => { + THelper.script(org.vm, code); OConfig.codeYieldPeriod = code.length; }; diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index a9e98d2..1d4c887 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,8 +1,10 @@ describe("client/src/organism/VM", () => { const eq = require('lodash/isEqual'); const Observer = require('./../../../common/src/Observer'); + const EVENT_AMOUNT = require('./../../../client/src/share/Events').EVENT_AMOUNT; const OrganismDos = require('./../manager/plugins/organisms/dos/Organism'); const Helper = require('./../../../common/src/Helper'); + const THelper = require('./../../../common/tests/Helper'); const OConfig = require('./../manager/plugins/organisms/Config'); const VM = require('./VM'); const Num = require('./Num'); @@ -246,12 +248,27 @@ describe("client/src/organism/VM", () => { OConfig.orgAlivePeriod = alive; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); }); + it('Should return correct amount of run lines', () => { + const obs = new Observer(EVENT_AMOUNT); + const vm = new VM(obs, OperatorsDos, OConfig.orgOperatorWeights); + const org = new OrganismDos('0', 0, 0, {}); + const period = OConfig.codeYieldPeriod; + + OConfig.codeYieldPeriod = 2; + vm.insertLine(); + expect(vm.run(org)).toEqual(2); + + org.destroy(); + vm.destroy(); + obs.destroy(); + OConfig.codeYieldPeriod = period; + }); }); describe('Crossover', () => { it("Checking crossover with increasing child code", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -263,37 +280,22 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 3} }; - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); + THelper.script(vm1, [16000000, 16000001, 16000002, 16000003, 16000004]); + THelper.script(vm2, [17000000, 17000001, 17000002, 17000003, 17000004]); - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); - - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 17000001, - 17000002, - 17000003, - 16000003, - 16000004 - ])).toEqual(true); + i = -1; + vm1.crossover(vm2); + expect(vm1.code).toEqual([16000000, 17000001, 17000002, 17000003, 16000003, 16000004]); Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it("Checking crossover with decreasing child code", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); - const rand = Helper.rand; - let i = -1; + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); + const rand = Helper.rand; + let i = -1; Helper.rand = () => { i++; @@ -303,33 +305,20 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 1} }; - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); + THelper.script(vm1, [16000000, 16000001, 16000002, 16000003, 16000004]); + THelper.script(vm2, [17000000, 17000001, 17000002, 17000003, 17000004]); - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); - - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ - 16000000, - 17000001, - 16000003, - 16000004 - ])).toEqual(true); + i = -1; + vm1.crossover(vm2); + expect(vm1.code).toEqual([16000000, 17000001, 16000003, 16000004]); Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it("Checking crossover with the same child code size", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -341,20 +330,20 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 3} }; - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); - jsvm1._code.push(16000004); + vm1._code.push(16000000); + vm1._code.push(16000001); + vm1._code.push(16000002); + vm1._code.push(16000003); + vm1._code.push(16000004); - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); - jsvm2._code.push(17000004); + vm2._code.push(17000000); + vm2._code.push(17000001); + vm2._code.push(17000002); + vm2._code.push(17000003); + vm2._code.push(17000004); - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ + vm1.crossover(vm2); + expect(eq(vm1.code, [ 16000000, 17000001, 17000002, @@ -363,23 +352,23 @@ describe("client/src/organism/VM", () => { ])).toEqual(true); Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it("Checking crossover with no code size in parents", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); - jsvm1.crossover(jsvm2); - expect(jsvm1.size).toEqual(0); - expect(jsvm2.size).toEqual(0); + vm1.crossover(vm2); + expect(vm1.size).toEqual(0); + expect(vm2.size).toEqual(0); - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -391,24 +380,24 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 2} }; - jsvm2._code.push(17000000); - jsvm2._code.push(17000001); - jsvm2._code.push(17000002); - jsvm2._code.push(17000003); + vm2._code.push(17000000); + vm2._code.push(17000001); + vm2._code.push(17000002); + vm2._code.push(17000003); - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ + vm1.crossover(vm2); + expect(eq(vm1.code, [ 17000001, 17000002 ])).toEqual(true); Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { - const jsvm1 = new VM(() => {}, obs, () => {}); - const jsvm2 = new VM(() => {}, obs, () => {}); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -420,25 +409,25 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 0} }; - jsvm1._code.push(16000000); - jsvm1._code.push(16000001); - jsvm1._code.push(16000002); - jsvm1._code.push(16000003); + vm1._code.push(16000000); + vm1._code.push(16000001); + vm1._code.push(16000002); + vm1._code.push(16000003); - jsvm1.crossover(jsvm2); - expect(eq(jsvm1.code, [ + vm1.crossover(vm2); + expect(eq(vm1.code, [ 16000000, 16000003, ])).toEqual(true); - expect(jsvm2.size).toEqual(0); + expect(vm2.size).toEqual(0); Helper.rand = rand; - jsvm1.destroy(); - jsvm2.destroy(); + vm1.destroy(); + vm2.destroy(); }); it('Checking insertLine() method', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); expect(vm.size).toEqual(0); vm.insertLine(); @@ -449,7 +438,7 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); it('Checking insertLine() method 2', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Num.rand; Num.rand = () => 0xabcdefff; @@ -465,7 +454,7 @@ describe("client/src/organism/VM", () => { }); it('Checking copyLines() method', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Helper.rand; let i = -1; @@ -495,7 +484,7 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); it('Checking copyLines() method 2', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Helper.rand; let i = -1; @@ -525,7 +514,7 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); it('Checking copyLines() method 3', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Helper.rand; let i = -1; @@ -555,7 +544,7 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); it('Checking copyLines() method with no code', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Helper.rand; Helper.rand = () => 0; @@ -568,7 +557,7 @@ describe("client/src/organism/VM", () => { }); it('Checking updateLine() method', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let rand = Num.rand; Num.rand = () => 0xabcdefff; @@ -586,7 +575,7 @@ describe("client/src/organism/VM", () => { }); it('Checking removeLine() method', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); vm.insertLine(); expect(vm.size).toEqual(1); @@ -596,7 +585,7 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); it('Checking removeLine() for empty code', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); expect(vm.size).toEqual(0); vm.removeLine(); @@ -608,7 +597,7 @@ describe("client/src/organism/VM", () => { }); it('Checking getLine()', () => { - const vm = new VM(() => {}, obs, () => {}); + const vm = new VM(obs, OperatorsDos, []); let get = Num.rand; Num.rand = () => 0xabcdefff; diff --git a/common/tests/Helper.js b/common/tests/Helper.js index 204df87..209396a 100644 --- a/common/tests/Helper.js +++ b/common/tests/Helper.js @@ -3,8 +3,6 @@ * * @author flatline */ -const each = require('lodash/each'); - class Helper { /** * Waiting for obj.done property to be true and calls cb() callback @@ -84,6 +82,19 @@ class Helper { len && iterate(queue[i++]) || done(); } + + /** + * Inserts script into specified organism. Code may be presented + * as an array of numbers (native format) or as a binary string + * of bits, e.g.: '10 00 01 10 00000010 1111111111'. Spaces will + * be cut from this string. + * @param {VM} vm Destination virtual machine + * @param {Array} code Code we are inserting in + */ + static script(vm, code) { + for (let i = 0; i < code.length; i++) {vm.insertLine()} + for (let i = 0; i < code.length; i++) {vm.updateLine(i, typeof code[i] === 'string' ? parseInt(code[i].split(' ').join(''), 2) : code[i])} + } } module.exports = Helper; \ No newline at end of file From c1ab103a9053d8ab22d7852982f6aba262b9b770 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 19:11:46 +0200 Subject: [PATCH 262/291] fixed more tests #83 --- client/src/vm/VMSpec.js | 112 ++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 68 deletions(-) diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 1d4c887..80fe256 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -1,5 +1,4 @@ describe("client/src/organism/VM", () => { - const eq = require('lodash/isEqual'); const Observer = require('./../../../common/src/Observer'); const EVENT_AMOUNT = require('./../../../client/src/share/Events').EVENT_AMOUNT; const OrganismDos = require('./../manager/plugins/organisms/dos/Organism'); @@ -317,8 +316,8 @@ describe("client/src/organism/VM", () => { vm2.destroy(); }); it("Checking crossover with the same child code size", () => { - const vm1 = new VM(obs, OperatorsDos, []); - const vm2 = new VM(obs, OperatorsDos, []); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -330,27 +329,12 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 3} }; - vm1._code.push(16000000); - vm1._code.push(16000001); - vm1._code.push(16000002); - vm1._code.push(16000003); - vm1._code.push(16000004); - - vm2._code.push(17000000); - vm2._code.push(17000001); - vm2._code.push(17000002); - vm2._code.push(17000003); - vm2._code.push(17000004); + THelper.script(vm1, [16000000, 16000001, 16000002, 16000003, 16000004]); + THelper.script(vm2, [17000000, 17000001, 17000002, 17000003, 17000004]); + i = -1; vm1.crossover(vm2); - expect(eq(vm1.code, [ - 16000000, - 17000001, - 17000002, - 17000003, - 16000004 - ])).toEqual(true); - + expect(vm1.code).toEqual([16000000, 17000001, 17000002, 17000003, 16000004]); Helper.rand = rand; vm1.destroy(); vm2.destroy(); @@ -367,8 +351,8 @@ describe("client/src/organism/VM", () => { vm2.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other", () => { - const vm1 = new VM(obs, OperatorsDos, []); - const vm2 = new VM(obs, OperatorsDos, []); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -380,24 +364,19 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 2} }; - vm2._code.push(17000000); - vm2._code.push(17000001); - vm2._code.push(17000002); - vm2._code.push(17000003); + THelper.script(vm2, [17000000, 17000001, 17000002, 17000003]); + i = -1; vm1.crossover(vm2); - expect(eq(vm1.code, [ - 17000001, - 17000002 - ])).toEqual(true); + expect(vm1.code).toEqual([17000001, 17000002]); Helper.rand = rand; vm1.destroy(); vm2.destroy(); }); it("Checking crossover with no code size for one parent and twp lines of code for other 2", () => { - const vm1 = new VM(obs, OperatorsDos, []); - const vm2 = new VM(obs, OperatorsDos, []); + const vm1 = new VM(obs, OperatorsDos, []); + const vm2 = new VM(obs, OperatorsDos, []); const rand = Helper.rand; let i = -1; @@ -409,48 +388,17 @@ describe("client/src/organism/VM", () => { if (i === 3) {return 0} }; - vm1._code.push(16000000); - vm1._code.push(16000001); - vm1._code.push(16000002); - vm1._code.push(16000003); + THelper.script(vm1, [16000000, 16000001, 16000002, 16000003]); + i = -1; vm1.crossover(vm2); - expect(eq(vm1.code, [ - 16000000, - 16000003, - ])).toEqual(true); + expect(vm1.code).toEqual([16000000, 16000003]); expect(vm2.size).toEqual(0); Helper.rand = rand; vm1.destroy(); vm2.destroy(); }); - - it('Checking insertLine() method', () => { - const vm = new VM(obs, OperatorsDos, []); - - expect(vm.size).toEqual(0); - vm.insertLine(); - expect(vm.size).toEqual(1); - vm.insertLine(); - expect(vm.size).toEqual(2); - - vm.destroy(); - }); - it('Checking insertLine() method 2', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Num.rand; - - Num.rand = () => 0xabcdefff; - expect(vm.size).toEqual(0); - vm.insertLine(); - expect(vm.size).toEqual(1); - - expect(vm.code[0]).toEqual(0xabcdefff); - - Num.rand = rand; - vm.destroy(); - }); }); it('Checking copyLines() method', () => { @@ -556,6 +504,34 @@ describe("client/src/organism/VM", () => { vm.destroy(); }); + describe('insertLine() method', () => { + it('Checking insertLine() method', () => { + const vm = new VM(obs, OperatorsDos, []); + + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + vm.insertLine(); + expect(vm.size).toEqual(2); + + vm.destroy(); + }); + it('Checking insertLine() method 2', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Num.rand; + + Num.rand = () => 0xabcdefff; + expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + + expect(vm.code[0]).toEqual(0xabcdefff); + + Num.rand = rand; + vm.destroy(); + }); + }); + it('Checking updateLine() method', () => { const vm = new VM(obs, OperatorsDos, []); let rand = Num.rand; From 718c6219f1dbb4ba3e9244a471a1c261a44aee3b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 20:33:25 +0200 Subject: [PATCH 263/291] fixed tests for VM.js #83 --- client/src/vm/VM.js | 4 +- client/src/vm/VMSpec.js | 305 +++++++++++++++++++++------------------- package.json | 2 +- 3 files changed, 161 insertions(+), 150 deletions(-) diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 77743fb..22138f7 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -183,8 +183,8 @@ class VM extends Observer { } /** - * Takes few lines from itself and makes a copy of them. After that inserts - * them before or after copied part. All positions are random + * Takes few lines from itself and inserts them before or after copied + * part. All positions are random. * @return {Number} Amount of added/copied lines */ copyLines() { diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index 80fe256..ba7e2b1 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -401,107 +401,112 @@ describe("client/src/organism/VM", () => { }); }); - it('Checking copyLines() method', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Helper.rand; - let i = -1; - - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - Helper.rand = function () { - i++; - if (i === 0) { // start - return 1; - } else if (i === 1) { // end - return 2; - } else if (i === 2) { // rand(2) - return 0; - } else if (i === 3) { // rand(start) - return 0; - } - }; - expect(vm.size).toEqual(4); - vm.copyLines(); - expect(vm.size).toEqual(6); - expect(vm.code[0]).toEqual(vm.code[3]); - expect(vm.code[1]).toEqual(vm.code[4]); - - Helper.rand = rand; - vm.destroy(); - }); - it('Checking copyLines() method 2', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Helper.rand; - let i = -1; - - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - Helper.rand = function () { - i++; - if (i === 0) { // start - return 1; - } else if (i === 1) { // end - return 2; - } else if (i === 2) { // rand(2) - return 1; - } else if (i === 3) { // rand(codeLen - end) - return 0; - } - }; - expect(vm.size).toEqual(4); - vm.copyLines(); - expect(vm.size).toEqual(6); - expect(vm.code[1]).toEqual(vm.code[3]); - expect(vm.code[2]).toEqual(vm.code[4]); - - Helper.rand = rand; - vm.destroy(); - }); - it('Checking copyLines() method 3', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Helper.rand; - let i = -1; - - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - vm.insertLine(); - Helper.rand = function () { - i++; - if (i === 0) { // start - return 1; - } else if (i === 1) { // end - return 2; - } else if (i === 2) { // rand(2) - return 1; - } else if (i === 3) { // rand(codeLen - end) - return 1; - } - }; - expect(vm.size).toEqual(4); - vm.copyLines(); - expect(vm.size).toEqual(6); - expect(vm.code[1]).toEqual(vm.code[4]); - expect(vm.code[2]).toEqual(vm.code[5]); - - Helper.rand = rand; - vm.destroy(); - }); - it('Checking copyLines() method with no code', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Helper.rand; + describe('copyLines() method', () => { + it('Checking copyLines() method', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Helper.rand; + let i = -1; + + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + Helper.rand = function () { + i++; + if (i === 0) { // start + return 1; + } else if (i === 1) { // end + return 2; + } else if (i === 2) { // rand(2) + return 0; + } else if (i === 3) { // rand(start) + return 0; + } + }; + i = -1; + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[0]).toEqual(vm.code[3]); + expect(vm.code[1]).toEqual(vm.code[4]); + + Helper.rand = rand; + vm.destroy(); + }); + it('Checking copyLines() method 2', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Helper.rand; + let i = -1; + + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + Helper.rand = function () { + i++; + if (i === 0) { // start + return 1; + } else if (i === 1) { // end + return 2; + } else if (i === 2) { // rand(2) + return 1; + } else if (i === 3) { // rand(codeLen - end) + return 0; + } + }; + i = -1; + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[1]).toEqual(vm.code[3]); + expect(vm.code[2]).toEqual(vm.code[4]); + + Helper.rand = rand; + vm.destroy(); + }); + it('Checking copyLines() method 3', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Helper.rand; + let i = -1; - Helper.rand = () => 0; - expect(vm.size).toEqual(0); - vm.copyLines(); - expect(vm.size).toEqual(0); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + vm.insertLine(); + Helper.rand = function () { + i++; + if (i === 0) { // start + return 1; + } else if (i === 1) { // end + return 2; + } else if (i === 2) { // rand(2) + return 1; + } else if (i === 3) { // rand(codeLen - end) + return 1; + } + }; + i = -1; + expect(vm.size).toEqual(4); + vm.copyLines(); + expect(vm.size).toEqual(6); + expect(vm.code[1]).toEqual(vm.code[4]); + expect(vm.code[2]).toEqual(vm.code[5]); - Helper.rand = rand; - vm.destroy(); + Helper.rand = rand; + vm.destroy(); + }); + it('Checking copyLines() method with no code', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Helper.rand; + + Helper.rand = () => 0; + expect(vm.size).toEqual(0); + vm.copyLines(); + expect(vm.size).toEqual(0); + + Helper.rand = rand; + vm.destroy(); + }); }); describe('insertLine() method', () => { @@ -532,65 +537,71 @@ describe("client/src/organism/VM", () => { }); }); - it('Checking updateLine() method', () => { - const vm = new VM(obs, OperatorsDos, []); - let rand = Num.rand; + describe('updateLine() method', () => { + it('Checking updateLine() method', () => { + const vm = new VM(obs, OperatorsDos, []); + let rand = Num.rand; - Num.rand = () => 0xabcdefff; - vm.insertLine(); - expect(vm.code[0]).toEqual(0xabcdefff); + Num.rand = () => 0xabcdefff; + vm.insertLine(); + expect(vm.code[0]).toEqual(0xabcdefff); - vm.updateLine(0, 0xffffffff); - expect(vm.code[0]).toEqual(0xffffffff); + vm.updateLine(0, 0xffffffff); + expect(vm.code[0]).toEqual(0xffffffff); - vm.updateLine(0, 0x12345678); - expect(vm.code[0]).toEqual(0x12345678); + vm.updateLine(0, 0x12345678); + expect(vm.code[0]).toEqual(0x12345678); - Num.rand = rand; - vm.destroy(); + Num.rand = rand; + vm.destroy(); + }); }); - it('Checking removeLine() method', () => { - const vm = new VM(obs, OperatorsDos, []); + describe('removeLine() method', () => { + it('Checking removeLine() method', () => { + const vm = new VM(obs, OperatorsDos, []); - vm.insertLine(); - expect(vm.size).toEqual(1); - vm.removeLine(); - expect(vm.size).toEqual(0); + vm.insertLine(); + expect(vm.size).toEqual(1); + vm.removeLine(); + expect(vm.size).toEqual(0); - vm.destroy(); - }); - it('Checking removeLine() for empty code', () => { - const vm = new VM(obs, OperatorsDos, []); + vm.destroy(); + }); + it('Checking removeLine() for empty code', () => { + const vm = new VM(obs, OperatorsDos, []); - expect(vm.size).toEqual(0); - vm.removeLine(); - expect(vm.size).toEqual(0); - vm.removeLine(); - expect(vm.size).toEqual(0); + expect(vm.size).toEqual(0); + vm.removeLine(); + expect(vm.size).toEqual(0); + vm.removeLine(); + expect(vm.size).toEqual(0); - vm.destroy(); + vm.destroy(); + }); }); - it('Checking getLine()', () => { - const vm = new VM(obs, OperatorsDos, []); - let get = Num.rand; - - Num.rand = () => 0xabcdefff; - expect(vm.size).toEqual(0); - expect(vm.getLine(0)).toEqual(undefined); - expect(vm.getLine(1)).toEqual(undefined); - vm.insertLine(); - expect(vm.size).toEqual(1); - expect(vm.getLine(0)).toEqual(0xabcdefff); - - vm.removeLine(); - expect(vm.size).toEqual(0); - expect(vm.getLine(0)).toEqual(undefined); - expect(vm.getLine(1)).toEqual(undefined); - expect(vm.getLine(9)).toEqual(undefined); - - Num.rand = get; - vm.destroy(); + describe('getLine() method', () => { + it('Checking getLine()', () => { + const vm = new VM(obs, OperatorsDos, []); + let get = Num.rand; + + Num.rand = () => 0xabcdefff; + expect(vm.size).toEqual(0); + expect(vm.getLine(0)).toEqual(undefined); + expect(vm.getLine(1)).toEqual(undefined); + vm.insertLine(); + expect(vm.size).toEqual(1); + expect(vm.getLine(0)).toEqual(0xabcdefff); + + vm.removeLine(); + expect(vm.size).toEqual(0); + expect(vm.getLine(0)).toEqual(undefined); + expect(vm.getLine(1)).toEqual(undefined); + expect(vm.getLine(9)).toEqual(undefined); + + Num.rand = get; + vm.destroy(); + }); }); }); \ No newline at end of file diff --git a/package.json b/package.json index d57ef03..5c98a7e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "construct", "version": "0.2.0", - "description": "JavaScript digital organisms simulator", + "description": "Construct - JavaScript digital organisms simulator", "main": "index.js", "directories": { "doc": "doc" From abde78b0b9bcb011e4319359e33941f383424978 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 22:48:36 +0200 Subject: [PATCH 264/291] fixed tests for Observer.js #83 optimized Observer.js --- common/src/Observer.js | 21 +-- common/src/ObserverSpec.js | 327 ++++++++++++++++++++----------------- 2 files changed, 182 insertions(+), 166 deletions(-) diff --git a/common/src/Observer.js b/common/src/Observer.js index 85948a2..24ebe80 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -35,22 +35,19 @@ class Observer { } off(event, handler) { - let index = -1; let handlers = this._handlers[event]; let len = handlers && handlers.amount; - if (handlers) { - for (let i = 0; i < len; i++) { - if (handlers[i] === handler) { - index = i; - handlers.amount = --len; - } - index > -1 && (handlers[i] = handlers[i+1]); + for (let i = 0; i < len; i++) { + if (handlers[i] === handler) { + handlers.amount = len - 1; + handlers[i] = handlers[i+1]; + delete handlers[handlers.amount]; + return true; } - delete handlers[handlers.amount]; } - return true; + return false; } /** @@ -61,8 +58,8 @@ class Observer { * @param args */ fire(event, ...args) { - const handlers = this._handlers[event]; - const len = handlers.amount; + const handlers = this._handlers[event] || {}; + const len = +handlers.amount; for (let i = 0; i < len; i++) { handlers[i](...args); } diff --git a/common/src/ObserverSpec.js b/common/src/ObserverSpec.js index 53a08ed..26fd8a2 100644 --- a/common/src/ObserverSpec.js +++ b/common/src/ObserverSpec.js @@ -1,8 +1,5 @@ -// TODO: add two events test describe("common/src/share/Observer", () => { let Observer = require('./Observer'); - let Config = require('./../../client/src/share/Config').Config; - let Console = require('./../../client/src/share/Console'); const EVENT = 0; const EVENT2 = 1; let obs; @@ -10,162 +7,184 @@ describe("common/src/share/Observer", () => { beforeEach(() => obs = new Observer(2)); afterEach(() => obs = null); - it("Checking empty Observer creation", () => { - let o = new Observer(); - let flag = false; - - function handler() {flag = true} - Console.mode(Config.QUIET_NO); - o.on(EVENT, handler); - expect(flag).toEqual(false); - o.fire(EVENT); - expect(flag).toEqual(false); - Console.mode(Config.QUIET_IMPORTANT); + describe('Creation/Destroy', () => { + it("Checking empty Observer creation", () => { + let o = new Observer(); + let flag = false; + + function handler() {flag = true} + o.on(EVENT, handler); + expect(flag).toEqual(false); + o.fire(EVENT); + expect(flag).toEqual(false); + }); + it("Destroy Observer creation", () => { + let flag = false; + + function handler() {flag = true} + obs.on(EVENT, handler); + obs.fire(EVENT); + expect(flag).toEqual(true); + + flag = false; + obs.destroy(); + obs.fire(EVENT); + expect(flag).toEqual(false); + }); }); - it("Checking on()/fire() methods", () => { - let flag = false; - function handler() {flag = true} - - obs.on(EVENT, handler); - obs.fire(EVENT); - expect(flag).toEqual(true); - }); - it("Checking on()/fire() for two events", () => { - let flag = false; - - function handler() {flag = true} - - obs.on(EVENT, handler); - obs.on(EVENT2, handler); - obs.fire(EVENT); - flag = false; - obs.fire(EVENT2); - expect(flag).toEqual(true); - - flag = false; - obs.clear(); - obs.fire(EVENT); - obs.fire(EVENT2); - expect(flag).toEqual(false); - }); - it("Checking on() without firing", () => { - let flag = false; - - function handler() {flag = true} - - obs.on(EVENT, handler); - expect(flag).toEqual(false); - }); - it("Checking off() method", () => { - let flag = false; - - function handler() {flag = true} - - obs.on(EVENT, handler); - expect(obs.off(EVENT, handler)).toEqual(true); - obs.fire(EVENT); - expect(flag).toEqual(false); - }); - it("Checking off() method with incorrect event id", () => { - let flag = false; - - function handler() {flag = true} - - obs.on(EVENT, handler); - expect(obs.off(EVENT2, handler)).toEqual(false); - obs.fire(EVENT); - expect(flag).toEqual(true); - }); - it("Checking double off() method", () => { - let flag = false; - - function handler() {flag = true} - - obs.on(EVENT, handler); - expect(obs.off(EVENT, handler)).toEqual(true); - expect(obs.off(EVENT, handler)).toEqual(false); - obs.fire(EVENT); - expect(flag).toEqual(false); - }); - it("Checking off() with no handlers", () => { - let flag = false; - - function handler() {flag = true} - - expect(obs.off(EVENT, handler)).toEqual(false); - obs.fire(EVENT); - expect(flag).toEqual(false); + describe('on/fire/off() methods', () => { + it("Checking on()/fire() methods", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + obs.fire(EVENT); + expect(flag).toEqual(true); + }); + it("Checking on()/fire() for two events", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + obs.on(EVENT2, handler); + obs.fire(EVENT); + flag = false; + obs.fire(EVENT2); + expect(flag).toEqual(true); + + flag = false; + obs.clear(); + obs.fire(EVENT); + obs.fire(EVENT2); + expect(flag).toEqual(false); + }); + it("Checking on() without firing", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + expect(flag).toEqual(false); + }); + it("Checking off() method", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + expect(obs.off(EVENT, handler)).toEqual(true); + obs.fire(EVENT); + expect(flag).toEqual(false); + }); + it("Checking off() method with incorrect event id", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + expect(obs.off(EVENT2, handler)).toEqual(false); + obs.fire(EVENT); + expect(flag).toEqual(true); + }); + it("Checking double off() method", () => { + let flag = false; + + function handler() {flag = true} + + obs.on(EVENT, handler); + expect(obs.off(EVENT, handler)).toEqual(true); + expect(obs.off(EVENT, handler)).toEqual(false); + obs.fire(EVENT); + expect(flag).toEqual(false); + }); + it("Checking off() with no handlers", () => { + let flag = false; + + function handler() {flag = true} + + expect(obs.off(EVENT, handler)).toEqual(false); + obs.fire(EVENT); + expect(flag).toEqual(false); + }); + it("Checking two event handlers", () => { + let inc = 0; + + function handler1() {inc++} + function handler2() {inc++} + + obs.on(EVENT, handler1); + obs.on(EVENT, handler2); + obs.fire(EVENT); + expect(inc).toEqual(2); + }); }); - it("Checking two event handlers", () => { - let inc = 0; - function handler1() {inc++} - function handler2() {inc++} - - obs.on(EVENT, handler1); - obs.on(EVENT, handler2); - obs.fire(EVENT); - expect(inc).toEqual(2); - }); - it("Checking complex behavior", () => { - let inc = 0; - - function handler1() {inc++} - function handler2() {inc++} - - obs.on(EVENT, handler1); - obs.on(EVENT, handler1); - obs.on(EVENT, handler2); - expect(obs.off(EVENT, handler1)).toEqual(true); - obs.fire(EVENT); - expect(inc).toEqual(2); - expect(obs.off(EVENT, handler1)).toEqual(true); - obs.fire(EVENT); - expect(inc).toEqual(3); - }); - it("Checking complex behavior 2", () => { - let inc = 0; - - function handler1() {inc++} - function handler2() {inc++} - - obs.on(EVENT, handler1); - obs.on(EVENT, handler1); - obs.on(EVENT, handler2); - obs.fire(EVENT); - obs.fire(EVENT); - expect(inc).toEqual(6); + describe('Complex tests', () => { + it("Checking complex behavior", () => { + let inc = 0; + + function handler1() {inc++} + function handler2() {inc++} + + obs.on(EVENT, handler1); + obs.on(EVENT, handler1); + obs.on(EVENT, handler2); + expect(obs.off(EVENT, handler1)).toEqual(true); + obs.fire(EVENT); + expect(inc).toEqual(2); + expect(obs.off(EVENT, handler1)).toEqual(true); + obs.fire(EVENT); + expect(inc).toEqual(3); + }); + it("Checking complex behavior 2", () => { + let inc = 0; + + function handler1() {inc++} + function handler2() {inc++} + + obs.on(EVENT, handler1); + obs.on(EVENT, handler1); + obs.on(EVENT, handler2); + obs.fire(EVENT); + obs.fire(EVENT); + expect(inc).toEqual(6); + }); }); - it("Checking clear() method", () => { - let inc = 0; - - function handler1() {inc++} - function handler2() {inc++} - - obs.on(EVENT, handler1); - obs.on(EVENT, handler2); - obs.clear(); - obs.fire(EVENT); - expect(inc).toEqual(0); - - obs.on(EVENT, handler1); - obs.fire(EVENT); - expect(inc).toEqual(1); - }); - it("Checking clear() method and fire with incorrect event id", () => { - let inc = 0; - - function handler() {inc++} - - obs.on(EVENT, handler); - obs.clear(); - obs.fire(EVENT); - obs.fire(EVENT2); - expect(inc).toEqual(0); - obs.on(EVENT, handler); - obs.fire(EVENT2); - expect(inc).toEqual(0); + describe('clear() method', () => { + it("Checking clear() method", () => { + let inc = 0; + + function handler1() {inc++} + function handler2() {inc++} + + obs.on(EVENT, handler1); + obs.on(EVENT, handler2); + obs.clear(); + obs.fire(EVENT); + expect(inc).toEqual(0); + + obs.on(EVENT, handler1); + obs.fire(EVENT); + expect(inc).toEqual(1); + }); + it("Checking clear() method and fire with incorrect event id", () => { + let inc = 0; + + function handler() {inc++} + + obs.on(EVENT, handler); + obs.clear(); + obs.fire(EVENT); + obs.fire(EVENT2); + expect(inc).toEqual(0); + + obs.on(EVENT, handler); + obs.fire(EVENT2); + expect(inc).toEqual(0); + }); }); }); \ No newline at end of file From c278318c4c617221eef3e175d758e24a1149a27b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 4 Mar 2018 23:54:54 +0200 Subject: [PATCH 265/291] fixed more tests #83 --- common/src/Observer.js | 3 +-- server/src/server/ServerSpec.js | 6 ++++++ server/src/server/plugins/ApiSpec.js | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/common/src/Observer.js b/common/src/Observer.js index 24ebe80..97e879c 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -59,8 +59,7 @@ class Observer { */ fire(event, ...args) { const handlers = this._handlers[event] || {}; - const len = +handlers.amount; - for (let i = 0; i < len; i++) { + for (let i = 0; i < +handlers.amount; i++) { handlers[i](...args); } } diff --git a/server/src/server/ServerSpec.js b/server/src/server/ServerSpec.js index c4df35a..161f0c3 100644 --- a/server/src/server/ServerSpec.js +++ b/server/src/server/ServerSpec.js @@ -194,6 +194,7 @@ describe("server/src/server/Server", () => { server.stop(); Helper.wait(waitObj, () => { server.destroy(); + ws.close(); done(); }); }); @@ -210,6 +211,8 @@ describe("server/src/server/Server", () => { Helper.wait(waitObj, () => { server.on(SEVENTS.STOP, () => waitObj.done = true); server.stop(); + ws1.close(); + ws2.close(); Helper.wait(waitObj, () => { server.destroy(); done(); @@ -231,6 +234,7 @@ describe("server/src/server/Server", () => { Helper.wait(waitObj, () => { server.on(SEVENTS.STOP, () => waitObj.done = true); server.stop(); + ws1.close(); Helper.wait(waitObj, () => { server.destroy(); done(); @@ -263,6 +267,7 @@ describe("server/src/server/Server", () => { expect(server.active).toEqual(true); server.on(SEVENTS.STOP, () => waitObj.done = true); server.destroy(); + ws.close(); Helper.wait(waitObj, () => { expect(server.active).toEqual(false); done(); @@ -279,6 +284,7 @@ describe("server/src/server/Server", () => { } run() {} stop() {} + resetActive() {} get clientId() {return this._clientId} set clientId(id) {this._clientId = id} } diff --git a/server/src/server/plugins/ApiSpec.js b/server/src/server/plugins/ApiSpec.js index 257cb9e..5eb2689 100644 --- a/server/src/server/plugins/ApiSpec.js +++ b/server/src/server/plugins/ApiSpec.js @@ -62,8 +62,9 @@ describe("server/src/server/plugins/Api", () => { this.activeAround = [false,false,false,false]; this._clientId = null; } - run() {} + run() {} stop() {} + resetActive() {} get clientId() {return this._clientId} set clientId(id) {this._clientId = id} } @@ -97,6 +98,7 @@ describe("server/src/server/plugins/Api", () => { } run() {} stop() {} + resetActive() {} set clientId(id) {this._clientId = id} } let maxCon = SConfig.maxConnections; From 0408094748b68e571cbf279663fd568e50898d0f Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 5 Mar 2018 09:53:40 +0200 Subject: [PATCH 266/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 235 +++++++++++++++--------------- 1 file changed, 120 insertions(+), 115 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 13eaf43..ed138f9 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -1,117 +1,122 @@ -// describe("client/src/manager/Manager", () => { -// const SERVER_HOST = 'ws://127.0.0.1'; -// const Config = require('./../../../client/src/share/Config').Config; -// const OConfig = require('./../manager/plugins/organisms/Config'); -// const SConfig = require('./../../../server/src/share/Config').Config; -// const Server = require('./../../../server/src/server/Server').Server; -// const EVENTS = require('./../../../client/src/share/Events').EVENTS; -// const SEVENTS = require('./../../../server/src/server/Server').EVENTS; -// const Console = require('./../../../client/src/share/Console'); -// const SConsole = require('./../../../server/src/share/Console'); -// const THelper = require('./../../../common/tests/Helper'); -// const ConfigHelper = require('./../../../common/tests/Config'); -// const World = require('./../../../client/src/view/World').World; -// const Manager = require('./Manager'); -// const emptyFn = () => {}; -// const waitEvent = THelper.waitEvent; -// const wait = THelper.wait; -// const testQ = THelper.testQ; -// const host = Config.serverHost; -// const port = SConfig.port; -// const maxConns = SConfig.maxConnections; -// const startOrgs = OConfig.orgStartAmount; -// const energyCheck = Config.worldEnergyCheckPeriod; -// -// let error; -// let warn; -// let info; -// let serror; -// let swarn; -// let sinfo; -// let dist; -// let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; -// -// function deletePluginConfigs() { -// delete Config.ips; -// delete Config.organisms; -// delete Config.status; -// delete Config.charts; -// delete Config.console; -// } -// -// beforeEach(() => { -// deletePluginConfigs(); -// }); -// beforeAll(() => { -// jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; -// Config.serverHost = SERVER_HOST; -// Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); -// dist = SConfig.modeDistributed; -// SConfig.modeDistributed = false; -// SConfig.port = Config.serverPort; -// SConfig.maxConnections = 100; -// OConfig.orgStartAmount = 0; -// Config.worldEnergyCheckPeriod = 0; -// -// error = Console.error; -// warn = Console.warn; -// info = Console.info; -// Console.error = emptyFn; -// Console.warn = emptyFn; -// Console.info = emptyFn; -// -// serror = SConsole.error; -// swarn = SConsole.warn; -// sinfo = SConsole.info; -// SConsole.error = emptyFn; -// SConsole.warn = emptyFn; -// SConsole.info = emptyFn; -// }); -// afterAll(() => { -// SConsole.error = serror; -// SConsole.warn = swarn; -// SConsole.info = sinfo; -// -// Console.error = error; -// Console.warn = warn; -// Console.info = info; -// Config.plugIncluded.push('ips/Ips'); -// jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; -// Config.serverHost = host; -// SConfig.modeDistributed = dist; -// SConfig.port = port; -// SConfig.maxConnections = maxConns; -// OConfig.orgStartAmount = startOrgs; -// Config.worldEnergyCheckPeriod = energyCheck; -// }); -// -// it("Checking manager creation", (done) => { -// const man = new Manager(false); -// expect(man.canvas).toBe(null); -// man.destroy(done); -// }); -// it("Checking manager creation and it's properties", (done) => { -// const man = new Manager(false); -// expect(man.organisms.size).toBe(0); -// expect(Object.keys(man.positions).length).toBe(0); -// expect(man.codeRuns).toBe(0); -// expect(!!man.api.version).toBe(true); -// expect(man.api.visualize).toBe(undefined); -// expect(man.active).toBe(false); -// expect(man.clientId).toBe(null); -// expect(man.isDistributed()).toBe(false); -// expect(man.canvas).toBe(null); -// man.destroy(done); -// }); -// it("Checking creation of two managers", (done) => { -// const man1 = new Manager(false); -// deletePluginConfigs(); -// const man2 = new Manager(false); -// -// waitEvent(man1, EVENTS.DESTROY, () => man1.destroy(), () => { -// waitEvent(man2, EVENTS.DESTROY, () => man2.destroy(), done); -// }); -// }); +describe("client/src/manager/Manager", () => { + const SERVER_HOST = 'ws://127.0.0.1'; + const Config = require('./../../../client/src/share/Config').Config; + const OConfig = require('./../manager/plugins/organisms/Config'); + const SConfig = require('./../../../server/src/share/Config').Config; + const Server = require('./../../../server/src/server/Server').Server; + const EVENTS = require('./../../../client/src/share/Events').EVENTS; + const SEVENTS = require('./../../../server/src/server/Server').EVENTS; + const Console = require('./../../../client/src/share/Console'); + const SConsole = require('./../../../server/src/share/Console'); + const THelper = require('./../../../common/tests/Helper'); + const ConfigHelper = require('./../../../common/tests/Config'); + const World = require('./../../../client/src/view/World').World; + const Manager = require('./Manager'); + const emptyFn = () => {}; + const waitEvent = THelper.waitEvent; + const wait = THelper.wait; + const testQ = THelper.testQ; + const host = Config.serverHost; + const port = SConfig.port; + const maxConns = SConfig.maxConnections; + const startOrgs = OConfig.orgStartAmount; + const energyCheck = Config.worldEnergyCheckPeriod; + + let error; + let warn; + let info; + let serror; + let swarn; + let sinfo; + let dist; + let timeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + + function deletePluginConfigs() { + delete Config.ips; + delete Config.organisms; + delete Config.status; + delete Config.charts; + delete Config.console; + } + + beforeEach(() => deletePluginConfigs()); + beforeAll(() => { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + Config.serverHost = SERVER_HOST; + Config.plugIncluded.splice(Config.plugIncluded.indexOf('ips/Ips')); + dist = SConfig.modeDistributed; + SConfig.modeDistributed = false; + SConfig.port = Config.serverPort; + SConfig.maxConnections = 100; + OConfig.orgStartAmount = 0; + Config.worldEnergyCheckPeriod = 0; + + error = Console.error; + warn = Console.warn; + info = Console.info; + Console.error = emptyFn; + Console.warn = emptyFn; + Console.info = emptyFn; + + serror = SConsole.error; + swarn = SConsole.warn; + sinfo = SConsole.info; + SConsole.error = emptyFn; + SConsole.warn = emptyFn; + SConsole.info = emptyFn; + }); + afterAll(() => { + SConsole.error = serror; + SConsole.warn = swarn; + SConsole.info = sinfo; + + Console.error = error; + Console.warn = warn; + Console.info = info; + Config.plugIncluded.push('ips/Ips'); + jasmine.DEFAULT_TIMEOUT_INTERVAL = timeout; + Config.serverHost = host; + SConfig.modeDistributed = dist; + SConfig.port = port; + SConfig.maxConnections = maxConns; + OConfig.orgStartAmount = startOrgs; + Config.worldEnergyCheckPeriod = energyCheck; + }); + + describe('Manager creation', () => { + it("Checking manager creation without view", (done) => { + const man = new Manager(false); + expect(man.canvas).toBe(null); + man.destroy(done); + }); + it("Checking manager creation and it's properties", (done) => { + const man = new Manager(false); + expect(man.organisms.size).toBe(0); + expect(Object.keys(man.positions).length).toBe(0); + expect(man.codeRuns).toBe(0); + expect(!!man.api.version).toBe(true); + expect(man.api.visualize).toBe(undefined); + expect(man.active).toBe(false); + expect(man.clientId).toBe(null); + expect(man.isDistributed()).toBe(false); + expect(man.canvas).toBe(null); + expect(man.active).toBe(false); + expect(man.world instanceof World).toBe(true); + expect(man.activeAround).toEqual([false, false, false, false]); + man.destroy(done); + }); + it("Checking creation of two managers", (done) => { + const man1 = new Manager(false); + deletePluginConfigs(); + const man2 = new Manager(false); + + testQ(done, + [man1, EVENTS.DESTROY, () => man1.destroy(), () => {}], + [man2, EVENTS.DESTROY, () => man2.destroy(), () => {}] + ); + }); + }); + // it("Checking creation 100 managers", (done) => { // const mans = []; // const amount = 100; @@ -864,4 +869,4 @@ // [man3, EVENTS.STEP_IN, () => {}, () => destroy()] // ); // }); -// }); \ No newline at end of file +}); \ No newline at end of file From c11bbf5ed6b7a1c691a7e3517199657f5bb197c5 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 5 Mar 2018 23:46:04 +0200 Subject: [PATCH 267/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 586 +++++++++++++++--------------- 1 file changed, 298 insertions(+), 288 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index ed138f9..e35a6bd 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -12,7 +12,6 @@ describe("client/src/manager/Manager", () => { const ConfigHelper = require('./../../../common/tests/Config'); const World = require('./../../../client/src/view/World').World; const Manager = require('./Manager'); - const emptyFn = () => {}; const waitEvent = THelper.waitEvent; const wait = THelper.wait; const testQ = THelper.testQ; @@ -21,6 +20,7 @@ describe("client/src/manager/Manager", () => { const maxConns = SConfig.maxConnections; const startOrgs = OConfig.orgStartAmount; const energyCheck = Config.worldEnergyCheckPeriod; + const emp = () => {}; let error; let warn; @@ -54,16 +54,16 @@ describe("client/src/manager/Manager", () => { error = Console.error; warn = Console.warn; info = Console.info; - Console.error = emptyFn; - Console.warn = emptyFn; - Console.info = emptyFn; + Console.error = emp; + Console.warn = emp; + Console.info = emp; serror = SConsole.error; swarn = SConsole.warn; sinfo = SConsole.info; - SConsole.error = emptyFn; - SConsole.warn = emptyFn; - SConsole.info = emptyFn; + SConsole.error = emp; + SConsole.warn = emp; + SConsole.info = emp; }); afterAll(() => { SConsole.error = serror; @@ -83,7 +83,7 @@ describe("client/src/manager/Manager", () => { Config.worldEnergyCheckPeriod = energyCheck; }); - describe('Manager creation', () => { + describe('Manager creation/destroy', () => { it("Checking manager creation without view", (done) => { const man = new Manager(false); expect(man.canvas).toBe(null); @@ -111,279 +111,296 @@ describe("client/src/manager/Manager", () => { const man2 = new Manager(false); testQ(done, - [man1, EVENTS.DESTROY, () => man1.destroy(), () => {}], - [man2, EVENTS.DESTROY, () => man2.destroy(), () => {}] + [man1, EVENTS.DESTROY, () => man1.destroy(), emp], + [man2, EVENTS.DESTROY, () => man2.destroy(), emp] + ); + }); + it("Checking creation 100 managers", (done) => { + const mans = []; + const amount = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let destroyed = 0; + let waitObj = {done: false}; + + Config.worldWidth = 10; + Config.worldHeight = 10; + for (let i = 0; i < amount; i++) {deletePluginConfigs(); mans.push(new Manager(false))} + for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} + + if (waitObj.done) { + Config.worldWidth = width; + Config.worldHeight = height; + done(); + return; + } + wait(waitObj, () => { + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }, 31000); + }); + it("Checking DESTROY event", (done) => { + const man = new Manager(false); + testQ(done, + [man, EVENTS.RUN, () => man.run(), emp], + [man, EVENTS.STOP, () => man.stop(), emp], + [man, EVENTS.DESTROY, () => man.destroy(), emp] ); }); }); -// it("Checking creation 100 managers", (done) => { -// const mans = []; -// const amount = 100; -// const width = Config.worldWidth; -// const height = Config.worldHeight; -// let destroyed = 0; -// let waitObj = {done: false}; -// -// Config.worldWidth = 10; -// Config.worldHeight = 10; -// for (let i = 0; i < amount; i++) {deletePluginConfigs(); mans.push(new Manager(false))} -// for (let i = 0; i < amount; i++) {mans[i].destroy(() => ++destroyed === amount && (waitObj.done = true))} -// -// if (waitObj.done) { -// Config.worldWidth = width; -// Config.worldHeight = height; -// done(); -// return; -// } -// wait(waitObj, () => { -// Config.worldWidth = width; -// Config.worldHeight = height; -// done(); -// }, 31000); -// }); -// -// it("Checking running manager", (done) => { -// const man = new Manager(false); -// man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); -// }); -// it("Checking if manager runs main loop", (done) => { -// const man = new Manager(false); -// let count = 0; -// man.run(() => man.on(EVENTS.ITERATION, () => { -// ++count === 100 && man.destroy(done); -// })); -// }); -// -// it("Checking RUN event", (done) => { -// const man = new Manager(false); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); -// }); -// it("Checking STOP event", (done) => { -// const man = new Manager(false); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => { -// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); -// }); -// }); -// it("Checking DESTROY event", (done) => { -// const man = new Manager(false); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => { -// waitEvent(man, EVENTS.STOP, () => man.stop(), () => { -// waitEvent(man, EVENTS.DESTROY, () => man.destroy(), done); -// }); -// }); -// }); -// it("Checking ITERATION event", (done) => { -// const man = new Manager(false); -// let ok = false; -// -// man.on(EVENTS.ITERATION, () => ok = true); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => { -// expect(ok).toBe(true); -// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); -// }); -// }); -// -// it("Checking isDistributed() method", (done) => { -// const man = new Manager(false); -// -// expect(man.isDistributed()).toBe(false); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => { -// expect(man.isDistributed()).toBe(false); -// waitEvent(man, EVENTS.STOP, () => man.stop(), () => { -// expect(man.isDistributed()).toBe(false); -// man.destroy(done); -// }); -// }); -// }); -// it("Checking 'codeRuns' property", (done) => { -// const man = new Manager(false); -// let ok = false; -// -// man.on(EVENTS.ITERATION, () => ok = true); -// expect(man.codeRuns).toBe(0); -// waitEvent(man, EVENTS.RUN, () => man.run(), () => { -// // codeRuns should be 0, because there is no code lines -// expect(man.codeRuns).toBe(0); -// waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); -// }); -// }); -// -// it("Checking running of manager with a server", (done) => { -// const server = new Server(); -// const man = new Manager(false); -// -// expect(man.clientId).toBe(null); -// waitEvent(server, SEVENTS.RUN, () => server.run(), () => { -// man.run(() => { -// expect(man.active).toBe(true); -// expect(man.clientId !== null).toBe(true); -// man.destroy(() => { -// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); -// }); -// }); -// }); -// }); -// -// it("Checking one organism creation in a manager", (done) => { -// const man = new Manager(false); -// const amount = OConfig.orgStartAmount; -// const period = OConfig.orgRainMutationPeriod; -// const percent = OConfig.orgCloneMutationPercent; -// const clone = OConfig.orgClonePeriod; -// let iterated = false; -// -// OConfig.orgStartAmount = 1; -// OConfig.orgRainMutationPeriod = 0; -// OConfig.orgCloneMutationPercent = 0; -// OConfig.orgClonePeriod = 0; -// expect(man.organisms.size).toBe(0); -// man.on(EVENTS.LOOP, () => { -// if (iterated) {return} -// expect(man.organisms.size).toBe(1); -// man.stop(() => { -// man.destroy(() => { -// OConfig.orgClonePeriod = clone; -// OConfig.orgCloneMutationPercent = percent; -// OConfig.orgRainMutationPeriod = period; -// OConfig.orgStartAmount = amount; -// done(); -// }); -// }); -// iterated = true; -// }); -// man.run(); -// }); -// it("Checking two managers with a server", (done) => { -// const amount = OConfig.orgStartAmount; -// const period = OConfig.orgRainMutationPeriod; -// const percent = OConfig.orgCloneMutationPercent; -// const period1 = OConfig.orgEnergySpendPeriod; -// const clone = OConfig.orgClonePeriod; -// const max = OConfig.orgMaxOrgs; -// const server = new Server(); -// const man1 = new Manager(false); -// deletePluginConfigs(); -// const man2 = new Manager(false); -// let iterated1 = false; -// let iterated2 = false; -// let blocked = false; -// const destroy = () => { -// blocked = true; -// man1.destroy(() => { -// man2.destroy(() => { -// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { -// OConfig.orgClonePeriod = clone; -// OConfig.orgEnergySpendPeriod = period1; -// OConfig.orgCloneMutationPercent = percent; -// OConfig.orgRainMutationPeriod = period; -// OConfig.orgStartAmount = amount; -// OConfig.orgMaxOrgs = max; -// done(); -// }); -// }); -// }); -// }; -// -// OConfig.orgStartAmount = 1; -// OConfig.orgRainMutationPeriod = 0; -// OConfig.orgCloneMutationPercent = 0; -// OConfig.orgEnergySpendPeriod = 0; -// OConfig.orgClonePeriod = 0; -// OConfig.orgMaxOrgs = 1; -// expect(man1.clientId).toBe(null); -// expect(man2.clientId).toBe(null); -// expect(man1.organisms.size).toBe(0); -// expect(man2.organisms.size).toBe(0); -// -// man1.on(EVENTS.LOOP, () => { -// if (blocked) {return} -// expect(man1.organisms.size).toBe(1); -// if (iterated1 && iterated2) {destroy(); return} -// iterated1 = true; -// }); -// man2.on(EVENTS.LOOP, () => { -// if (blocked) {return} -// expect(man2.organisms.size).toBe(1); -// if (iterated2 && iterated1) {destroy(); return} -// iterated2 = true; -// }); -// -// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { -// man1.run(() => { -// expect(man1.active).toBe(true); -// expect(man1.clientId !== null).toBe(true); -// man2.run(() => { -// expect(man2.active).toBe(true); -// expect(man2.clientId !== null).toBe(true); -// }); -// }); -// }); -// }); -// -// it("Checking moving of organism from one Manager to another", (done) => { -// const amount = OConfig.orgStartAmount; -// const period = OConfig.orgRainMutationPeriod; -// const percent = OConfig.orgCloneMutationPercent; -// const period1 = OConfig.orgEnergySpendPeriod; -// const clone = OConfig.orgClonePeriod; -// const width = Config.worldWidth; -// const height = Config.worldHeight; -// const energy = OConfig.orgStartEnergy; -// const max = OConfig.orgMaxOrgs; -// const server = new Server(); -// Config.worldWidth = 400; -// Config.worldHeight = 400; -// const man1 = new Manager(false); -// deletePluginConfigs(); -// const man2 = new Manager(false); -// let iterated1 = 0; -// let iterated2 = 0; -// let freePos = World.prototype.getFreePos; -// let org1 = null; -// const destroy = () => { -// man1.destroy(() => { -// man2.destroy(() => { -// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { -// World.prototype.getFreePos = freePos; -// OConfig.orgStartEnergy = energy; -// OConfig.orgClonePeriod = clone; -// OConfig.orgEnergySpendPeriod = period1; -// OConfig.orgCloneMutationPercent = percent; -// OConfig.orgRainMutationPeriod = period; -// OConfig.orgStartAmount = amount; -// Config.worldWidth = width; -// Config.worldHeight = height; -// OConfig.orgMaxOrgs = max; -// done(); -// }); -// }); -// }); -// }; -// -// OConfig.orgStartAmount = 1; -// OConfig.orgRainMutationPeriod = 0; -// OConfig.orgCloneMutationPercent = 0; -// OConfig.orgEnergySpendPeriod = 0; -// OConfig.orgClonePeriod = 0; -// OConfig.orgStartEnergy = 10000; -// OConfig.orgMaxOrgs = 2; -// World.prototype.getFreePos = () => {return {x: 399, y: 1}}; -// -// man1.on(EVENTS.LOOP, () => { -// if (iterated1 > 0 && iterated2 > 0 && org1 === null) { -// org1 = man1.organisms.first.val; -// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() -// } else if (man2.organisms.size === 2) { -// destroy(); -// } -// if (iterated1 > 10000) {throw 'Error sending organism between Managers'} -// iterated1++; -// }); -// man2.on(EVENTS.LOOP, () => iterated2++); -// -// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); -// }); + describe('Run/Stop manager', () => { + it("Checking running manager", (done) => { + const man = new Manager(false); + man.run(() => man.on(EVENTS.ITERATION, () => man.destroy(done))); + }); + it("Checking RUN event", (done) => { + const man = new Manager(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => man.destroy(done)); + }); + it("Checking STOP event", (done) => { + const man = new Manager(false); + testQ(done, + [man, EVENTS.RUN, () => man.run(), emp], + [man, EVENTS.STOP, () => man.stop(), emp], + [man, EVENTS.DESTROY, () => man.destroy(), emp] + ); + }); + }); + + describe('Main loop checks', () => { + it("Checking if manager runs main loop", (done) => { + const man = new Manager(false); + let count = 0; + man.run(() => man.on(EVENTS.ITERATION, () => { + ++count === 100 && man.destroy(done); + })); + }); + it("Checking ITERATION event", (done) => { + const man = new Manager(false); + let ok = false; + + man.on(EVENTS.ITERATION, () => ok = true); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + expect(ok).toBe(true); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + it("Checking LOOP event", (done) => { + const man = new Manager(false); + let ok = false; + + man.on(EVENTS.LOOP, () => ok = true); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + expect(ok).toBe(true); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + }); + + describe('isDistributed() method', () => { + it("Checking isDistributed() method", (done) => { + const man = new Manager(false); + + expect(man.isDistributed()).toBe(false); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + expect(man.isDistributed()).toBe(false); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => { + expect(man.isDistributed()).toBe(false); + man.destroy(done); + }); + }); + }); + }); + + describe('codeRunc property', () => { + it("Checking 'codeRuns' property", (done) => { + const man = new Manager(false); + let ok = false; + + man.on(EVENTS.ITERATION, () => ok = true); + expect(man.codeRuns).toBe(0); + waitEvent(man, EVENTS.RUN, () => man.run(), () => { + // codeRuns should be 0, because there is no code lines + expect(man.codeRuns).toBe(0); + waitEvent(man, EVENTS.STOP, () => man.stop(), () => man.destroy(done)); + }); + }); + }); + + describe('Managers with a server', () => { + it("Checking running of manager with a server", (done) => { + const server = new Server(); + const man = new Manager(false); + + expect(man.clientId).toBe(null); + waitEvent(server, SEVENTS.RUN, () => server.run(), () => { + man.run(() => { + expect(man.active).toBe(true); + expect(man.clientId !== null).toBe(true); + man.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), done); + }); + }); + }); + }); + it("Checking two managers with a server", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const max = OConfig.orgMaxOrgs; + const log = console.log; + const server = new Server(); + const man1 = new Manager(false); + deletePluginConfigs(); + const man2 = new Manager(false); + let iterated1 = false; + let iterated2 = false; + let blocked = false; + const destroy = () => { + blocked = true; + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + OConfig.orgMaxOrgs = max; + console.log = log; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgMaxOrgs = 1; + console.log = () => {}; + expect(man1.clientId).toBe(null); + expect(man2.clientId).toBe(null); + expect(man1.organisms.size).toBe(0); + expect(man2.organisms.size).toBe(0); + + man1.on(EVENTS.LOOP, () => { + if (blocked) {return} + expect(man1.organisms.size).toBe(1); + if (iterated1 && iterated2) {destroy(); return} + iterated1 = true; + }); + man2.on(EVENTS.LOOP, () => { + if (blocked) {return} + expect(man2.organisms.size).toBe(1); + if (iterated2 && iterated1) {destroy(); return} + iterated2 = true; + }); + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + man1.run(() => { + expect(man1.active).toBe(true); + expect(man1.clientId !== null).toBe(true); + man2.run(() => { + expect(man2.active).toBe(true); + expect(man2.clientId !== null).toBe(true); + }); + }); + }); + }); + }); + + describe('Organism related tests', () => { + it("Checking one organism creation in a manager", (done) => { + const man = new Manager(false); + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + let iterated = false; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + expect(man.organisms.size).toBe(0); + man.on(EVENTS.LOOP, () => { + if (iterated) {return} + expect(man.organisms.size).toBe(1); + man.stop(() => { + man.destroy(() => { + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + done(); + }); + }); + iterated = true; + }); + man.run(); + }); + // it("Checking moving of organism from one Manager to another", (done) => { + // const amount = OConfig.orgStartAmount; + // const period = OConfig.orgRainMutationPeriod; + // const percent = OConfig.orgCloneMutationPercent; + // const period1 = OConfig.orgEnergySpendPeriod; + // const width = Config.worldWidth; + // const height = Config.worldHeight; + // const energy = OConfig.orgStartEnergy; + // const max = OConfig.orgMaxOrgs; + // const server = new Server(); + // Config.worldWidth = 400; + // Config.worldHeight = 400; + // const man1 = new Manager(false); + // deletePluginConfigs(); + // const man2 = new Manager(false); + // let iterated1 = 0; + // let iterated2 = 0; + // let freePos = World.prototype.getFreePos; + // let org1 = null; + // const destroy = () => { + // man1.destroy(() => { + // man2.destroy(() => { + // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + // World.prototype.getFreePos = freePos; + // OConfig.orgStartEnergy = energy; + // OConfig.orgEnergySpendPeriod = period1; + // OConfig.orgCloneMutationPercent = percent; + // OConfig.orgRainMutationPeriod = period; + // OConfig.orgStartAmount = amount; + // Config.worldWidth = width; + // Config.worldHeight = height; + // OConfig.orgMaxOrgs = max; + // done(); + // }); + // }); + // }); + // }; + // + // OConfig.orgStartAmount = 1; + // OConfig.orgRainMutationPeriod = 0; + // OConfig.orgCloneMutationPercent = 0; + // OConfig.orgEnergySpendPeriod = 0; + // OConfig.orgStartEnergy = 10000; + // OConfig.orgMaxOrgs = 2; + // World.prototype.getFreePos = () => {return {x: 399, y: 1}}; + // + // man1.on(EVENTS.LOOP, () => { + // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + // org1 = man1.organisms.first.val; + // org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() + // } else if (man2.organisms.size === 2) { + // destroy(); + // } + // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + // iterated1++; + // }); + // man2.on(EVENTS.LOOP, () => iterated2++); + // + // waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); + // }); + }); // /** // * The meaning of this test is in checking if one organism from up manager // * will go into the down manager, but there will be another organism. First @@ -394,7 +411,6 @@ describe("client/src/manager/Manager", () => { // const period = OConfig.orgRainMutationPeriod; // const percent = OConfig.orgCloneMutationPercent; // const period1 = OConfig.orgEnergySpendPeriod; -// const clone = OConfig.orgClonePeriod; // const height = Config.worldHeight; // const energy = OConfig.orgStartEnergy; // const max = OConfig.orgMaxOrgs; @@ -417,7 +433,6 @@ describe("client/src/manager/Manager", () => { // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { // World.prototype.getFreePos = freePos; // OConfig.orgStartEnergy = energy; -// OConfig.orgClonePeriod = clone; // OConfig.orgEnergySpendPeriod = period1; // OConfig.orgCloneMutationPercent = percent; // OConfig.orgRainMutationPeriod = period; @@ -434,7 +449,6 @@ describe("client/src/manager/Manager", () => { // OConfig.orgRainMutationPeriod = 0; // OConfig.orgCloneMutationPercent = 0; // OConfig.orgEnergySpendPeriod = 0; -// OConfig.orgClonePeriod = 0; // OConfig.orgStartEnergy = 10000; // OConfig.orgMaxOrgs = 1; // World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; @@ -535,8 +549,8 @@ describe("client/src/manager/Manager", () => { // [waitObj], // [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], // [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], -// [server, SEVENTS.CLOSE, () => man1.destroy(), () => {}], -// [server, SEVENTS.CLOSE, () => man2.destroy(), () => {}], +// [server, SEVENTS.CLOSE, () => man1.destroy(), emp], +// [server, SEVENTS.CLOSE, () => man2.destroy(), emp], // [server, SEVENTS.DESTROY, () => server.destroy(), () => { // SConfig.maxConnections = maxCons; // Config.worldWidth = width; @@ -646,7 +660,6 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgRainMutationPeriod', 0); // ocfg.set('orgCloneMutationPercent',0); // ocfg.set('orgEnergySpendPeriod', 0); -// ocfg.set('orgClonePeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); // World.prototype.getFreePos = () => {return {x: 1, y: 9}}; @@ -724,7 +737,6 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgRainMutationPeriod', 0); // ocfg.set('orgCloneMutationPercent',0); // ocfg.set('orgEnergySpendPeriod', 0); -// ocfg.set('orgClonePeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); // World.prototype.getFreePos = () => {return {x: 0, y: 1}}; @@ -800,7 +812,6 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgRainMutationPeriod', 0); // ocfg.set('orgCloneMutationPercent',0); // ocfg.set('orgEnergySpendPeriod', 0); -// ocfg.set('orgClonePeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); // World.prototype.getFreePos = () => {return {x: 5, y: 1}}; @@ -858,15 +869,14 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgRainMutationPeriod', 0); // ocfg.set('orgCloneMutationPercent', 0); // ocfg.set('orgEnergySpendPeriod', 0); -// ocfg.set('orgClonePeriod', 0); // ocfg.set('orgStartEnergy', 10000); // World.prototype.getFreePos = () => {return {x: 5, y: ++i === 1 ? 1 : 2}}; // // testQ(done, // [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], // [waitObj], -// [man1, EVENTS.LOOP, () => {}, () => man1.organisms.first.val.vm.code.push(0b00001011000000000000000000000000)], // onStepRight() -// [man3, EVENTS.STEP_IN, () => {}, () => destroy()] +// [man1, EVENTS.LOOP, emp, () => man1.organisms.first.val.vm.code.push(0b00001011000000000000000000000000)], // onStepRight() +// [man3, EVENTS.STEP_IN, emp, () => destroy()] // ); // }); }); \ No newline at end of file From 5b5214068b91b6e1c79c257d9a4f8b2b7af39ab6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 6 Mar 2018 18:35:51 +0200 Subject: [PATCH 268/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 131 +++++++++--------- .../plugins/organisms/dos/Organisms.js | 2 +- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index e35a6bd..63b4c90 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -340,66 +340,67 @@ describe("client/src/manager/Manager", () => { }); man.run(); }); - // it("Checking moving of organism from one Manager to another", (done) => { - // const amount = OConfig.orgStartAmount; - // const period = OConfig.orgRainMutationPeriod; - // const percent = OConfig.orgCloneMutationPercent; - // const period1 = OConfig.orgEnergySpendPeriod; - // const width = Config.worldWidth; - // const height = Config.worldHeight; - // const energy = OConfig.orgStartEnergy; - // const max = OConfig.orgMaxOrgs; - // const server = new Server(); - // Config.worldWidth = 400; - // Config.worldHeight = 400; - // const man1 = new Manager(false); - // deletePluginConfigs(); - // const man2 = new Manager(false); - // let iterated1 = 0; - // let iterated2 = 0; - // let freePos = World.prototype.getFreePos; - // let org1 = null; - // const destroy = () => { - // man1.destroy(() => { - // man2.destroy(() => { - // waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { - // World.prototype.getFreePos = freePos; - // OConfig.orgStartEnergy = energy; - // OConfig.orgEnergySpendPeriod = period1; - // OConfig.orgCloneMutationPercent = percent; - // OConfig.orgRainMutationPeriod = period; - // OConfig.orgStartAmount = amount; - // Config.worldWidth = width; - // Config.worldHeight = height; - // OConfig.orgMaxOrgs = max; - // done(); - // }); - // }); - // }); - // }; - // - // OConfig.orgStartAmount = 1; - // OConfig.orgRainMutationPeriod = 0; - // OConfig.orgCloneMutationPercent = 0; - // OConfig.orgEnergySpendPeriod = 0; - // OConfig.orgStartEnergy = 10000; - // OConfig.orgMaxOrgs = 2; - // World.prototype.getFreePos = () => {return {x: 399, y: 1}}; - // - // man1.on(EVENTS.LOOP, () => { - // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - // org1 = man1.organisms.first.val; - // org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - // } else if (man2.organisms.size === 2) { - // destroy(); - // } - // if (iterated1 > 10000) {throw 'Error sending organism between Managers'} - // iterated1++; - // }); - // man2.on(EVENTS.LOOP, () => iterated2++); - // - // waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); - // }); + it("Checking moving of organism from one Manager to another", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const width = Config.worldWidth; + const height = Config.worldHeight; + const energy = OConfig.orgStartEnergy; + const max = OConfig.orgMaxOrgs; + const server = new Server(); + Config.worldWidth = 400; + Config.worldHeight = 400; + const man1 = new Manager(false); + deletePluginConfigs(); + const man2 = new Manager(false); + let iterated1 = 0; + let iterated2 = 0; + let freePos = World.prototype.getFreePos; + let org1 = null; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldWidth = width; + Config.worldHeight = height; + OConfig.orgMaxOrgs = max; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgStartEnergy = 10000; + OConfig.orgMaxOrgs = 2; + World.prototype.getFreePos = () => {return [399, 1]}; + + man1.on(EVENTS.LOOP, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + org1 = man1.organisms.first.val; + org1.vm.insertLine(); + org1.vm.updateLine(0, 0b00001011000000000000000000000000); // onStepRight() + } else if (man2.organisms.size === 2) { + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + iterated1++; + }); + man2.on(EVENTS.LOOP, () => iterated2++); + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); + }); }); // /** // * The meaning of this test is in checking if one organism from up manager @@ -451,7 +452,7 @@ describe("client/src/manager/Manager", () => { // OConfig.orgEnergySpendPeriod = 0; // OConfig.orgStartEnergy = 10000; // OConfig.orgMaxOrgs = 1; -// World.prototype.getFreePos = () => {return inc++ === 0 && {x: 399, y: 1} || {x: 0, y: 1}}; +// World.prototype.getFreePos = () => {return inc++ === 0 && [399, 1] || [0, 1]}; // // man1.on(EVENTS.LOOP, () => { // if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { @@ -662,7 +663,7 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgEnergySpendPeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); -// World.prototype.getFreePos = () => {return {x: 1, y: 9}}; +// World.prototype.getFreePos = () => {return [1, 9]}; // // man1.on(EVENTS.LOOP, () => { // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { @@ -739,7 +740,7 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgEnergySpendPeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); -// World.prototype.getFreePos = () => {return {x: 0, y: 1}}; +// World.prototype.getFreePos = () => {return [0, 1]}; // // man1.on(EVENTS.LOOP, () => { // if (iterated1 > 0 && iterated2 > 0 && org1 === null) { @@ -814,7 +815,7 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgEnergySpendPeriod', 0); // ocfg.set('orgStartEnergy', 10000); // cfg.set('worldCyclical', false); -// World.prototype.getFreePos = () => {return {x: 5, y: 1}}; +// World.prototype.getFreePos = () => {return [5, 1]}; // // man1.on(EVENTS.LOOP, () => { // if (iterated1 > 0 && org1 === null) { @@ -870,7 +871,7 @@ describe("client/src/manager/Manager", () => { // ocfg.set('orgCloneMutationPercent', 0); // ocfg.set('orgEnergySpendPeriod', 0); // ocfg.set('orgStartEnergy', 10000); -// World.prototype.getFreePos = () => {return {x: 5, y: ++i === 1 ? 1 : 2}}; +// World.prototype.getFreePos = () => {return [5, ++i === 1 ? 1 : 2]}; // // testQ(done, // [server, SEVENTS.RUN, () => server.run(), () => {man1.run(() => man2.run(() => man3.run(() => waitObj.done = true)))}], diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 0ce8319..26c0df1 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -231,7 +231,7 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg({x, y})) { + if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg(x, y)) { const org = this.organisms.last.val; org.unserialize(orgJson); const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; From 453f03876b4c065ecfcf8be82d55c1131e8b01c1 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 6 Mar 2018 20:13:57 +0200 Subject: [PATCH 269/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 168 +++++++++++++++--------------- 1 file changed, 84 insertions(+), 84 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 63b4c90..7481113 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -399,93 +399,93 @@ describe("client/src/manager/Manager", () => { }); man2.on(EVENTS.LOOP, () => iterated2++); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); + }); + /** + * The meaning of this test is in checking if one organism from left manager + * will go to the right manager, but there will be another organism. First + * organism should die in this case. + */ + it("Checking moving of organism from one Manager to another 2", (done) => { + const amount = OConfig.orgStartAmount; + const period = OConfig.orgRainMutationPeriod; + const percent = OConfig.orgCloneMutationPercent; + const period1 = OConfig.orgEnergySpendPeriod; + const height = Config.worldHeight; + const energy = OConfig.orgStartEnergy; + const max = OConfig.orgMaxOrgs; + const server = new Server(); + Config.worldHeight = 400; + Config.worldWidth = 400; + const man1 = new Manager(false); + deletePluginConfigs(); + const man2 = new Manager(false); + let iterated1 = 0; + let iterated2 = 0; + let freePos = World.prototype.getFreePos; + let org1 = null; + let org2 = null; + let inc = 0; + let doneInc = 0; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { + World.prototype.getFreePos = freePos; + OConfig.orgStartEnergy = energy; + OConfig.orgEnergySpendPeriod = period1; + OConfig.orgCloneMutationPercent = percent; + OConfig.orgRainMutationPeriod = period; + OConfig.orgStartAmount = amount; + Config.worldHeight = height; + OConfig.orgMaxOrgs = max; + done(); + }); + }); + }); + }; + + OConfig.orgStartAmount = 1; + OConfig.orgRainMutationPeriod = 0; + OConfig.orgCloneMutationPercent = 0; + OConfig.orgEnergySpendPeriod = 0; + OConfig.orgStartEnergy = 10000; + OConfig.orgMaxOrgs = 1; + World.prototype.getFreePos = () => {return inc++ === 0 && [399, 1] || [0, 1]}; + + man1.on(EVENTS.LOOP, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() + man1.on(EVENTS.STEP_OUT, () => { + expect(doneInc < 3).toBe(true); + ++doneInc; + }); + man2.on(EVENTS.STEP_IN, () => { + ++doneInc; + expect(man1.organisms.size).toBe(1); + expect(man1.organisms.first.val.x).toBe(0); + }); + } else if (org1 !== null && org2 !== null && doneInc === 2) { + expect(man1.organisms.size).toBe(1); + expect(man1.organisms.first.val.x).toBe(0); + expect(man2.organisms.size).toBe(1); + expect(man2.organisms.first.val.x).toBe(0); + destroy(); + doneInc++; + } + if (iterated1 > 10000) {throw 'Error sending organism between Managers'} + iterated1++; + }); + man2.on(EVENTS.LOOP, () => { + !iterated2 && (org2 = man2.organisms.first.val); + iterated2++; + }); + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); }); }); -// /** -// * The meaning of this test is in checking if one organism from up manager -// * will go into the down manager, but there will be another organism. First -// * organism should die in this case. -// */ -// it("Checking moving of organism from one Manager to another 2", (done) => { -// const amount = OConfig.orgStartAmount; -// const period = OConfig.orgRainMutationPeriod; -// const percent = OConfig.orgCloneMutationPercent; -// const period1 = OConfig.orgEnergySpendPeriod; -// const height = Config.worldHeight; -// const energy = OConfig.orgStartEnergy; -// const max = OConfig.orgMaxOrgs; -// const server = new Server(); -// Config.worldHeight = 400; -// Config.worldWidth = 400; -// const man1 = new Manager(false); -// deletePluginConfigs(); -// const man2 = new Manager(false); -// let iterated1 = 0; -// let iterated2 = 0; -// let freePos = World.prototype.getFreePos; -// let org1 = null; -// let org2 = null; -// let inc = 0; -// let doneInc = 0; -// const destroy = () => { -// man1.destroy(() => { -// man2.destroy(() => { -// waitEvent(server, SEVENTS.DESTROY, () => server.destroy(), () => { -// World.prototype.getFreePos = freePos; -// OConfig.orgStartEnergy = energy; -// OConfig.orgEnergySpendPeriod = period1; -// OConfig.orgCloneMutationPercent = percent; -// OConfig.orgRainMutationPeriod = period; -// OConfig.orgStartAmount = amount; -// Config.worldHeight = height; -// OConfig.orgMaxOrgs = max; -// done(); -// }); -// }); -// }); -// }; -// -// OConfig.orgStartAmount = 1; -// OConfig.orgRainMutationPeriod = 0; -// OConfig.orgCloneMutationPercent = 0; -// OConfig.orgEnergySpendPeriod = 0; -// OConfig.orgStartEnergy = 10000; -// OConfig.orgMaxOrgs = 1; -// World.prototype.getFreePos = () => {return inc++ === 0 && [399, 1] || [0, 1]}; -// -// man1.on(EVENTS.LOOP, () => { -// if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { -// org1 = man1.organisms.first.val; -// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() -// man1.on(EVENTS.STEP_OUT, () => { -// expect(doneInc < 3).toBe(true); -// ++doneInc; -// }); -// man2.on(EVENTS.STEP_IN, () => { -// ++doneInc; -// expect(man1.organisms.size).toBe(1); -// expect(man1.organisms.first.val.x).toBe(0); -// }); -// } else if (org1 !== null && org2 !== null && doneInc === 2) { -// expect(man1.organisms.size).toBe(1); -// expect(man1.organisms.first.val.x).toBe(0); -// expect(man2.organisms.size).toBe(1); -// expect(man2.organisms.first.val.x).toBe(0); -// destroy(); -// doneInc++; -// } -// if (iterated1 > 10000) {throw 'Error sending organism between Managers'} -// iterated1++; -// }); -// man2.on(EVENTS.LOOP, () => { -// !iterated2 && (org2 = man2.organisms.first.val); -// iterated2++; -// }); -// -// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); -// }); -// + // it("Testing hundred managers and one server", (done) => { // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; // const maxCons = SConfig.maxConnections; From 9d4b78fc14013bfe67bbb5742d3e10a1850dcaf4 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 8 Mar 2018 16:17:13 +0200 Subject: [PATCH 270/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 160 ++++++++++++++++-------------- 1 file changed, 87 insertions(+), 73 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 7481113..9ac508d 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -170,6 +170,10 @@ describe("client/src/manager/Manager", () => { }); describe('Main loop checks', () => { + let log; + beforeAll(() => {log = console.log; console.log = () => {}}); + afterAll (() => console.log = log); + it("Checking if manager runs main loop", (done) => { const man = new Manager(false); let count = 0; @@ -486,79 +490,89 @@ describe("client/src/manager/Manager", () => { }); }); -// it("Testing hundred managers and one server", (done) => { -// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; -// const maxCons = SConfig.maxConnections; -// const server = new Server(); -// const mans = []; -// const CLIENTS = 100; -// const width = Config.worldWidth; -// const height = Config.worldHeight; -// let amount = 0; -// let waitObj = {done: false}; -// let man; -// -// Config.worldWidth = 100; -// Config.worldHeight = 100; -// SConfig.maxConnections = CLIENTS; -// -// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { -// for (let i = 0; i < CLIENTS; i++) { -// deletePluginConfigs(); -// mans.push(man = new Manager(false)); -// man.run(() => ++amount === CLIENTS && (waitObj.done = true)); -// } -// wait(waitObj, () => { -// amount = 0; -// server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); -// for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} -// wait(waitObj, () => { -// waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { -// SConfig.maxConnections = maxCons; -// Config.worldWidth = width; -// Config.worldHeight = height; -// done(); -// }); -// }); -// }, 31000); -// }); -// }); -// it("Testing run/stop/run manager and one server", (done) => { -// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; -// const maxCons = SConfig.maxConnections; -// const server = new Server(); -// const CLIENTS = 100; -// const width = Config.worldWidth; -// const height = Config.worldHeight; -// let amount = 0; -// let waitObj = {done: false}; -// let count = 0; -// const onDone = () => ++count === 2 && (waitObj.done = true); -// let man1; -// let man2; -// let oldId; -// -// Config.worldWidth = 100; -// Config.worldHeight = 100; -// SConfig.maxConnections = CLIENTS; -// man1 = new Manager(false); -// deletePluginConfigs(); -// man2 = new Manager(false); -// -// testQ(done, -// [server, SEVENTS.RUN, () => server.run(), () => {man1.run(onDone); man2.run(onDone)}], -// [waitObj], -// [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], -// [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], -// [server, SEVENTS.CLOSE, () => man1.destroy(), emp], -// [server, SEVENTS.CLOSE, () => man2.destroy(), emp], -// [server, SEVENTS.DESTROY, () => server.destroy(), () => { -// SConfig.maxConnections = maxCons; -// Config.worldWidth = width; -// Config.worldHeight = height; -// }] -// ); -// }); + describe('Client/Server tests', () => { + let originalTimeout; + beforeEach(() => { + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; + }); + afterEach(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout); + + it("Testing hundred managers and one server", (done) => { + const log = console.log; + const maxCons = SConfig.maxConnections; + const server = new Server(); + const mans = []; + const CLIENTS = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let amount = 0; + let waitObj = {done: false}; + let man; + + console.log = () => {}; + Config.worldWidth = 100; + Config.worldHeight = 100; + SConfig.maxConnections = CLIENTS; + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + for (let i = 0; i < CLIENTS; i++) { + deletePluginConfigs(); + mans.push(man = new Manager(false)); + man.run(() => ++amount === CLIENTS && (waitObj.done = true)); + } + wait(waitObj, () => { + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === CLIENTS && (waitObj.done = true)); + for (let i = 0; i < CLIENTS; i++) {mans[i].destroy()} + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + console.log = log; + done(); + }); + }); + }, 61000); + }); + }); + it("Testing run/stop/run manager and one server", (done) => { + const maxCons = SConfig.maxConnections; + const server = new Server(); + const CLIENTS = 100; + const width = Config.worldWidth; + const height = Config.worldHeight; + let amount = 0; + let waitObj = {done: false}; + let count = 0; + const onDone = () => ++count === 2 && (waitObj.done = true); + let man1; + let man2; + let oldId; + + Config.worldWidth = 100; + Config.worldHeight = 100; + SConfig.maxConnections = CLIENTS; + man1 = new Manager(false); + deletePluginConfigs(); + man2 = new Manager(false); + + testQ(done, + [server, SEVENTS.RUN, () => server.run(), () => {man1.run(onDone); man2.run(onDone)}], + [waitObj], + [man1, EVENTS.STOP, () => man1.stop(), () => {expect(man1.clientId).toBe(null); oldId = man1.clientId}], + [man1, EVENTS.RUN, () => man1.run(), () => {expect(man1.clientId).not.toBe(null); amount = 0; waitObj.done = false}], + [server, SEVENTS.CLOSE, () => man1.destroy(), emp], + [server, SEVENTS.CLOSE, () => man2.destroy(), emp], + [server, SEVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + }] + ); + }); + }); // // it("Tests many connections/disconnections of Manager to the server", (done) => { // jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; From ceaef2e55b0b89b28b68dad0575d6e010b93027b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 8 Mar 2018 16:44:24 +0200 Subject: [PATCH 271/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 101 +++++++++++++++--------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 9ac508d..849a716 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -572,58 +572,57 @@ describe("client/src/manager/Manager", () => { }] ); }); + it("Tests many connections/disconnections of Manager to the server", (done) => { + const maxCons = SConfig.maxConnections; + const server = new Server(); + const CLIENTS = 16; + const width = Config.worldWidth; + const height = Config.worldHeight; + let waitObj = {done: false}; + let amount = 0; + let count = 0; + let man1; + let man2; + const cb = () => { + man1.stop(() => { + expect(man1.clientId).toBe(null); + man1.run(() => { + expect(man1.clientId).not.toBe(null); + if (++amount < 10) { + cb(); + return; + } + man1.destroy(); + man2.destroy(); + amount = 0; + server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); + wait(waitObj, () => { + waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { + SConfig.maxConnections = maxCons; + Config.worldWidth = width; + Config.worldHeight = height; + done(); + }); + }); + }); + }); + }; + + Config.worldWidth = 10; + Config.worldHeight = 10; + SConfig.maxConnections = CLIENTS; + man1 = new Manager(false); + deletePluginConfigs(); + man2 = new Manager(false); + + waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { + man1.run(() => ++count === 2 && (waitObj.done = true)); + man2.run(() => ++count === 2 && (waitObj.done = true)); + wait(waitObj, cb); + }); + }); }); -// -// it("Tests many connections/disconnections of Manager to the server", (done) => { -// jasmine.DEFAULT_TIMEOUT_INTERVAL = 35000; -// const maxCons = SConfig.maxConnections; -// const server = new Server(); -// const CLIENTS = 16; -// const width = Config.worldWidth; -// const height = Config.worldHeight; -// let waitObj = {done: false}; -// let amount = 0; -// let count = 0; -// let man1; -// let man2; -// const cb = () => { -// man1.stop(() => { -// expect(man1.clientId).toBe(null); -// man1.run(() => { -// expect(man1.clientId).not.toBe(null); -// if (++amount < 10) { -// cb(); -// return; -// } -// man1.destroy(); -// man2.destroy(); -// amount = 0; -// server.on(server.EVENTS.CLOSE, () => ++amount === 2 && (waitObj.done = true)); -// wait(waitObj, () => { -// waitEvent(server, server.EVENTS.DESTROY, () => server.destroy(), () => { -// SConfig.maxConnections = maxCons; -// Config.worldWidth = width; -// Config.worldHeight = height; -// done(); -// }); -// }); -// }); -// }); -// }; -// -// Config.worldWidth = 10; -// Config.worldHeight = 10; -// SConfig.maxConnections = CLIENTS; -// man1 = new Manager(false); -// deletePluginConfigs(); -// man2 = new Manager(false); -// -// waitEvent(server, server.EVENTS.RUN, () => server.run(), () => { -// man1.run(() => ++count === 2 && (waitObj.done = true)); -// man2.run(() => ++count === 2 && (waitObj.done = true)); -// wait(waitObj, cb); -// }); -// }); + // // it('Tests organism moving from client of one server to client of other server', (done) => { // const ocfg = new ConfigHelper(OConfig); From e9dbeaa6690688da94765c71b1df5164fda16dd3 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 8 Mar 2018 17:50:14 +0200 Subject: [PATCH 272/291] fixed more tests #83 --- client/src/manager/ManagerSpec.js | 164 ++++++++++++++++-------------- 1 file changed, 88 insertions(+), 76 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 849a716..acb5714 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -318,6 +318,13 @@ describe("client/src/manager/Manager", () => { }); describe('Organism related tests', () => { + let originalTimeout; + beforeEach(() => { + originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; + jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000; + }); + afterEach(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout); + it("Checking one organism creation in a manager", (done) => { const man = new Manager(false); const amount = OConfig.orgStartAmount; @@ -488,6 +495,87 @@ describe("client/src/manager/Manager", () => { waitEvent(server, server.EVENTS.RUN, () => server.run(), () => man1.run(() => man2.run())); }); + it('Tests organism moving from client of one server to client of other server', (done) => { + const log = console.log; + const ocfg = new ConfigHelper(OConfig); + const cfg = new ConfigHelper(Config); + const scfg = new ConfigHelper(SConfig); + const freePos = World.prototype.getFreePos; + let iterated1 = 0; + let iterated2 = 0; + let org1 = null; + const destroy = () => { + man1.destroy(() => { + man2.destroy(() => { + waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { + waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { + World.prototype.getFreePos = freePos; + ocfg.reset(); + scfg.reset(); + cfg.reset(); + console.log = log; + done(); + }); + }); + }); + }); + }; + + console.log = () => {}; + scfg.set('upHost', SERVER_HOST); + scfg.set('rightHost', SERVER_HOST); + scfg.set('downHost', SERVER_HOST); + scfg.set('leftHost', SERVER_HOST); + ocfg.set('codeIterationsPerOnce', 1); + scfg.set('modeDistributed', true); + scfg.set('maxConnections', 1); + scfg.set('port', 3000); + scfg.set('rightPort', 3001); + const server1 = new Server(); // left server + scfg.set('port', 3001); + scfg.set('leftPort', 3000); + scfg.set('rightPort', 1001); + const server2 = new Server(); // right server + cfg.set('worldWidth', 10); + cfg.set('worldHeight', 10); + cfg.set('serverPort', 3000); + cfg.set('serverHost', SERVER_HOST); + const man1 = new Manager(false); + deletePluginConfigs(); + cfg.set('serverPort', 3001); + const man2 = new Manager(false); + ocfg.set('orgStartAmount', 1); + ocfg.set('orgRainMutationPeriod', 0); + ocfg.set('orgCloneMutationPercent',0); + ocfg.set('orgEnergySpendPeriod', 0); + ocfg.set('orgStartEnergy', 10000); + cfg.set('worldCyclical', false); + World.prototype.getFreePos = () => {return [9, 1]}; + + man1.on(EVENTS.LOOP, () => { + if (iterated1 > 0 && iterated2 > 0 && org1 === null) { + log('loop'); + expect(man2.organisms.size).toBe(1); + org1 = man1.organisms.first.val; + org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() + } else if (man2.organisms.size === 2) { + log('destroy'); + destroy(); + } + if (iterated1 > 10000) {throw 'Error sending organism between Servers'} + iterated1++; + }); + man2.on(EVENTS.LOOP, () => iterated2++); + + waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { + log('server1 run'); + waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { + log('server2 run'); + man1.run(() => man2.run()); + }); + }); + }); + }); describe('Client/Server tests', () => { @@ -622,82 +710,6 @@ describe("client/src/manager/Manager", () => { }); }); }); - -// -// it('Tests organism moving from client of one server to client of other server', (done) => { -// const ocfg = new ConfigHelper(OConfig); -// const cfg = new ConfigHelper(Config); -// const scfg = new ConfigHelper(SConfig); -// const freePos = World.prototype.getFreePos; -// let iterated1 = 0; -// let iterated2 = 0; -// let org1 = null; -// const destroy = () => { -// man1.destroy(() => { -// man2.destroy(() => { -// waitEvent(server1, SEVENTS.DESTROY, () => server1.destroy(), () => { -// waitEvent(server2, SEVENTS.DESTROY, () => server2.destroy(), () => { -// World.prototype.getFreePos = freePos; -// ocfg.reset(); -// scfg.reset(); -// cfg.reset(); -// done(); -// }); -// }); -// }); -// }); -// }; -// -// scfg.set('upHost', SERVER_HOST); -// scfg.set('rightHost', SERVER_HOST); -// scfg.set('downHost', SERVER_HOST); -// scfg.set('leftHost', SERVER_HOST); -// ocfg.set('codeIterationsPerOnce', 1); -// scfg.set('modeDistributed', true); -// scfg.set('maxConnections', 1); -// scfg.set('port', 3000); -// scfg.set('rightPort', 3001); -// const server1 = new Server(); // up server -// scfg.set('port', 3001); -// scfg.set('leftPort', 3000); -// scfg.set('rightPort', 1001); -// const server2 = new Server(); // down server -// cfg.set('worldWidth', 10); -// cfg.set('worldHeight', 10); -// cfg.set('serverPort', 3000); -// cfg.set('serverHost', SERVER_HOST); -// const man1 = new Manager(false); -// deletePluginConfigs(); -// cfg.set('serverPort', 3001); -// const man2 = new Manager(false); -// ocfg.set('orgStartAmount', 1); -// ocfg.set('orgRainMutationPeriod', 0); -// ocfg.set('orgCloneMutationPercent',0); -// ocfg.set('orgEnergySpendPeriod', 0); -// ocfg.set('orgStartEnergy', 10000); -// cfg.set('worldCyclical', false); -// World.prototype.getFreePos = () => {return [1, 9]}; -// -// man1.on(EVENTS.LOOP, () => { -// if (iterated1 > 0 && iterated2 > 0 && org1 === null) { -// expect(man2.organisms.size).toBe(1); -// org1 = man1.organisms.first.val; -// org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() -// } else if (man2.organisms.size === 2) { -// destroy(); -// } -// if (iterated1 > 10000) {throw 'Error sending organism between Servers'} -// iterated1++; -// }); -// man2.on(EVENTS.LOOP, () => iterated2++); -// -// waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { -// waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { -// man1.run(man2.run); -// }); -// }); -// }); -// // it('Tests organism moving back from client of near server', (done) => { // const ocfg = new ConfigHelper(OConfig); // const cfg = new ConfigHelper(Config); From 33bd8ad00527d3486927448fdeebf783d4a545c2 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Mon, 12 Mar 2018 16:43:45 +0200 Subject: [PATCH 273/291] fixed #128 --- client/src/manager/ManagerSpec.js | 4 -- .../src/manager/plugins/organisms/Config.js | 14 ++--- .../src/manager/plugins/organisms/Organism.js | 6 ++- .../plugins/organisms/dos/Code2String.js | 51 +++++++------------ client/src/vm/VM.js | 2 +- 5 files changed, 30 insertions(+), 47 deletions(-) diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index acb5714..1104b1a 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -554,12 +554,10 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - log('loop'); expect(man2.organisms.size).toBe(1); org1 = man1.organisms.first.val; org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() } else if (man2.organisms.size === 2) { - log('destroy'); destroy(); } if (iterated1 > 10000) {throw 'Error sending organism between Servers'} @@ -568,9 +566,7 @@ describe("client/src/manager/Manager", () => { man2.on(EVENTS.LOOP, () => iterated2++); waitEvent(server1, server1.EVENTS.RUN, () => server1.run(), () => { - log('server1 run'); waitEvent(server2, server2.EVENTS.RUN, () => server2.run(), () => { - log('server2 run'); man1.run(() => man2.run()); }); }); diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 4f28b4d..1adf25c 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. */ orgOperatorWeights: [ - .000001, .000001, .00000001, .00000000001, .0000001, // var, const, if, loop, operator, - .0000001, .0002, .0002, .0002, .0002, // lookAt, eatLeft, eatRight, eatUp, eatDown, - .002, .002, .002, .002, // stepLeft, stepRight, stepUp, stepDown, - .000001, .000001, // fromMem, toMem, - .0000001, .0000001, // myX, myY, - .000001, .000001, .000001, .000001 // checkLeft, checkRight, checkUp, checkDown + .0001, .0001, .000001, .000000001, .00001, // var, const, if, loop, operator, + .00001, .02, .02, .02, .02, // lookAt, eatLeft, eatRight, eatUp, eatDown, + .2, .2, .2, .2, // stepLeft, stepRight, stepUp, stepDown, + .0001, .0001, // fromMem, toMem, + .00001, .00001, // myX, myY, + .0001, .0001, .0001, .0001 // checkLeft, checkRight, checkUp, checkDown ], /** * {Array} Probabilities which used, when mutator decides what to do: @@ -146,7 +146,7 @@ const Config = { * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. */ - codeBitsPerVar: 4, + codeBitsPerVar: 2, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 9c96fdb..8d828b0 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -127,8 +127,10 @@ class Organism extends Observer { this._updateEnergy(); if (this._energy > 0) { this._updateClone(); - this._energy > 0 && this.fire(ITERATION, lines, this); - this._energy > 0 && this._updateAge(); + if (this._energy > 0) { + this.fire(ITERATION, lines, this); + this._energy > 0 && this._updateAge(); + } } return true; diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 013efb2..7cc2bce 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -59,7 +59,7 @@ class Code2String { /** * {Array} Contains closing bracket offset for "if", "loop",... operators */ - this._offsets = []; + this._offsets = [0]; Num.init(this._OPERATORS_CB_LEN); @@ -86,35 +86,28 @@ class Code2String { const operators = this._OPERATORS_CB; const offs = this._offsets; let lines = new Array(len); - let needClose = 0; - + // + // First number always amount of code lines + // + offs.splice(0, offs.length, len); for (let line = 0; line < len; line++) { + lines[line] = operators[Num.getOperator(code[line])](code[line], line); // // We found closing bracket '}' of some loop and have to add // it to output code array // - if (line === offs[offs.length - 1]) { - while (offs.length > 0 && offs[offs.length - 1] === line) { - offs.pop(); - needClose++; - } - } - lines[line] = operators[Num.getOperator(code[line])](code[line], line, len); - if (needClose > 0) { - for (let i = 0; i < needClose; i++) { - lines[line] = '}' + lines[line]; - } - needClose = 0; + while (offs.length > 1 && line === offs[offs.length - 1]) { + line = offs.pop(); + lines[line] += '}'; } } // // All closing brackets st the end of JS script // const length = lines.length - 1; - for (let i = 0; i < offs.length; i++) { + for (let i = 1; i < offs.length; i++) { lines[length] += '}'; } - offs.length = 0; return js_beautify(lines.join(separator), {indent_size: 4}); } @@ -134,22 +127,22 @@ class Code2String { } _onConst(num) { - return `v${Num.getVar0(num)}=${Num.getBits(num, this._BITS_AFTER_THREE_VARS, OConfig.codeConstBits)}`; + return `v${Num.getVar0(num)}=${Num.getBits(num, this._BITS_AFTER_ONE_VAR, OConfig.codeConstBits)}`; } - _onCondition(num, line, lines) { + _onCondition(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); const blockOffs = Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); - this._offsets.push(this._getOffs(line, lines, blockOffs)); + this._offsets.push(this._getOffs(line, blockOffs)); return `if(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } - _onLoop(num, line, lines) { + _onLoop(num, line) { const cond = Num.getBits(num, this._BITS_AFTER_TWO_VARS, CONDITION_BITS); const blockOffs = Num.getBits(num, this._BITS_AFTER_TWO_VARS + CONDITION_BITS, OConfig.codeBitsPerBlock); - this._offsets.push(this._getOffs(line, lines, blockOffs)); + this._offsets.push(this._getOffs(line, blockOffs)); return `while(v${Num.getVar0(num)}${this._CONDITIONS[cond]}v${Num.getVar1(num)}){`; } @@ -248,20 +241,12 @@ class Code2String { * So it's possible to set it to one of 1...3. So we change it in * real time to fix the overlap problem. * @param {Number} line Current line index - * @param {Number} lines Amount of lines * @param {Number} offs Local offset of closing bracket we want to set * @returns {Number} */ - _getOffs(line, lines, offs) { - let offset = line + offs < lines ? line + offs + 1 : lines; - const offsets = this._offsets; - const length = offsets.length; - - if (length > 0 && offset >= offsets[length - 1]) { - return offsets[length - 1]; - } - - return offset; + _getOffs(line, offs) { + const offsets = this._offsets || [0]; + return line + offs > offsets[offsets.length - 1] ? offsets[offsets.length - 1] : line + offs; } } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index 22138f7..df075bd 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -107,7 +107,7 @@ class VM extends Observer { // This is very important peace of logic. As big the organism is // as more energy he spends // - org.energy -= (WEIGHTS[operator] * org.energy + (org.vm ? org.vm.size : 0)); + org.energy -= WEIGHTS[operator]; // // We found closing bracket '}' of some loop and have to return // to the beginning of operator (e.g.: for) From 296ff85ff333e545fadc062d9a05bfe6761642a6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 13 Mar 2018 08:43:35 +0200 Subject: [PATCH 274/291] fixed tests #83 --- .../src/manager/plugins/organisms/Config.js | 2 +- .../plugins/organisms/dos/OrganismSpec.js | 5 ++-- client/src/vm/VMSpec.js | 2 +- server/src/server/ServerSpec.js | 29 ++++++++++++------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 1adf25c..ecba4b1 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -146,7 +146,7 @@ const Config = { * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. */ - codeBitsPerVar: 2, + codeBitsPerVar: 4, /** * {Number} Amount of bits for storing operator. This is first XX bits * in a number. diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 27281c9..636e920 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -82,7 +82,6 @@ describe("client/src/organism/OrganismDos", () => { OConfig.orgStartEnergy = energy; }); - it("Organism should not be dead after loosing some energy", () => { const period = OConfig.orgAlivePeriod; const energy = OConfig.orgStartEnergy; @@ -99,9 +98,9 @@ describe("client/src/organism/OrganismDos", () => { expect(org1.energy).toBe(100); org1.run(); - expect(org1.energy).toBe(89); // 100 - (100 * .1 + 1) = 89 + expect(org1.energy).toBe(99.9); // 100 - .1 = 99.9 org1.run(); - expect(org1.energy).toBe(79.1); // 90 - (90 * .1 + 1) = 79.1 + expect(org1.energy).toBe(99.80000000000001); // 99.9 - .1 = 99.8 org1.destroy(); expect(org1.energy < 1).toBe(true); diff --git a/client/src/vm/VMSpec.js b/client/src/vm/VMSpec.js index ba7e2b1..08fe69d 100644 --- a/client/src/vm/VMSpec.js +++ b/client/src/vm/VMSpec.js @@ -238,7 +238,7 @@ describe("client/src/organism/VM", () => { vm.updateLine(0, 0x00000000); expect(org.energy).toEqual(100); vm.run(org); - expect(org.energy).toEqual(90); // 100 - (100 * .1 + 0) = 90 + expect(org.energy).toEqual(99.9); // 100 - .1 = 99.9 org.destroy(); vm.destroy(); diff --git a/server/src/server/ServerSpec.js b/server/src/server/ServerSpec.js index 161f0c3..d4f7b1f 100644 --- a/server/src/server/ServerSpec.js +++ b/server/src/server/ServerSpec.js @@ -209,13 +209,17 @@ describe("server/src/server/Server", () => { const ws1 = new WebSocket(CLIENT_URL); const ws2 = new WebSocket(CLIENT_URL); Helper.wait(waitObj, () => { - server.on(SEVENTS.STOP, () => waitObj.done = true); - server.stop(); + cons = 0; + server.on(SEVENTS.CLOSE, () => ++cons === 2 && (waitObj.done = true)); ws1.close(); ws2.close(); Helper.wait(waitObj, () => { - server.destroy(); - done(); + server.on(SEVENTS.STOP, () => waitObj.done = true); + server.stop(); + Helper.wait(waitObj, () => { + server.destroy(); + done(); + }); }); }); }); @@ -232,12 +236,12 @@ describe("server/src/server/Server", () => { server.on(SEVENTS.CLOSE, () => waitObj.done = true); ws2.close(); Helper.wait(waitObj, () => { - server.on(SEVENTS.STOP, () => waitObj.done = true); - server.stop(); + server.on(SEVENTS.CLOSE, () => waitObj.done = true); ws1.close(); Helper.wait(waitObj, () => { + server.on(SEVENTS.DESTROY, () => waitObj.done = true); server.destroy(); - done(); + Helper.wait(waitObj, done); }); }) }); @@ -265,12 +269,15 @@ describe("server/src/server/Server", () => { const ws = new WebSocket(CLIENT_URL); Helper.wait(waitObj, () => { expect(server.active).toEqual(true); - server.on(SEVENTS.STOP, () => waitObj.done = true); - server.destroy(); + server.on(SEVENTS.CLOSE, () => waitObj.done = true); ws.close(); Helper.wait(waitObj, () => { - expect(server.active).toEqual(false); - done(); + server.on(SEVENTS.DESTROY, () => waitObj.done = true); + server.destroy(); + Helper.wait(waitObj, () => { + expect(server.active).toEqual(false); + done(); + }); }); }); }); From 290015655ad4aee40fd9e95ac9cb82b90d3c32e0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Mar 2018 13:30:40 +0200 Subject: [PATCH 275/291] added console API commends to the README #118 fixed small issue with extra mutations on start added min energy for ability to clone added description to API methods changed version to 0.2.1.1 --- README.md | 13 ++++++ client/src/manager/Manager.js | 6 ++- client/src/manager/plugins/Config.js | 7 ++-- .../src/manager/plugins/organisms/Config.js | 22 ++++++---- .../src/manager/plugins/organisms/Mutator.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 2 +- .../manager/plugins/organisms/Organisms.js | 41 ++++++++++++++++--- .../plugins/organisms/dos/Code2String.js | 3 +- .../plugins/organisms/dos/Operators.js | 4 +- .../plugins/organisms/dos/OrganismSpec.js | 5 ++- .../manager/plugins/status/charts/Charts.js | 2 +- common/src/Configurable.js | 3 +- common/src/Helper.js | 12 ++++++ 13 files changed, 93 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8ef7c8b..73e33a6 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,19 @@ - Run server `npm run server` on chosen host - Copy `./client/dist/index.html` and `./client/dist/app.js` on all your remote machines and run it there under Chrome +# Main commands +As an administrator, you may affect the system by command line API. For instance, you may obtain amount of organisms in current population or set new configuration in real time. For this, you have to open Chrome console (press `F12`) and type `man.api[.namespace].xxx()`. Where `namespace` is an optional unit or module and `xxx()` is supported command of this module. It's possible to use `desc` property to get command description. Example: `man.api.getConfig.desc`. Here are all available commands separated by namespace: +- global namespace - `man.api`: + - `man.api.visualize(show:Boolean = true)` - Turns on/off visualization in browser for current instance (world). Turning visualization off, increases application speed. + - `man.api.formatCode(code:Array)` - Converts byte code array into human readable JavaScript based code. This function is low level. For using it you have to get organism's virtual machine reference and then use it's `code` property. For example: `man.api.formatCode(man.api.organisms.getOrganism('128').vm.code)`. This example will find organism with id `128` and shows his byte code. + - `man.api.version` - Returns current app version + - `man.api.getConfig(path:String)` - Returns specified config value. First parameter is a namespace (optional) and config name. For example, to get maximum amount of organisms in current instance/world type: `man.api.getConfig('organisms.orgMaxOrgs')`. Example of organism related configs you may find [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/organisms/Config.js). Other configuration parameters are located in files with name `Config.js`. + - `man.api.setConfig(path:String, value:Any)` - Sets configuration value in real time. Opposite to `getConfig()`. +- charts namespace - `man.api.charts`. This namespace is related to statistics in charts. There are many parameters like average code size, organisms amount, amount of picked energy and so on. See details [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js) in charts property. You may show and hide different charts on a canvas, locate them and reset any time you need: + - `man.api.charts.on([[name:String = undefined[, show:Boolean = true]])` - shows chart(s) by name. List of all available names you may find [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). Example: `man.api.charts.on('energy')` - will show chart of average organism energy at the moment. Calling this method without parameters shows all available charts. Calling this method with only one string parameter shows specified chart. Calling this method with two parameters shows/hides specified chart depending on second Boolean parameter. Example: `man.api.charts.on()` - shows all charts. `man.api.charts.on('energy')` - shows energy chart only. `man.api.charts.on('energy', false)` - hides energy chart only. + - `man.api.charts.off(name:String = undefined)` - opposite to `on()`. Hides specified or all charts (without parameters) from the canvas. + - `man.api.charts.pos(String, String)` - Locates chart according to specified position. Available positions are: `full`, `top`, `down`, `left`, `right`, `topleft`, `downleft`, `topright`, `downright`. Example: `man.api.charts.pos('code', 'full')` - shows `code` trend chart on full screen. All available chart names are [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). + Note: to improve speed, type `man.api.visualize(false)` in Chrome's devtool console during application run ___ P.S. If you are a `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index c39461a..e18ef7b 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -20,6 +20,7 @@ const Plugins = require('./Plugins'); const EVENTS = require('./../share/Events').EVENTS; const EVENT_AMOUNT = require('./../share/Events').EVENT_AMOUNT; const Console = require('./../share/Console'); +const Helper = require('./../../../common/src/Helper'); const World = require('./../view/World').World; const WEVENTS = require('./../view/World').EVENTS; const Canvas = require('./../view/Canvas'); @@ -52,8 +53,9 @@ class Manager extends Observer { * It may be used in a user console by the Operator of construct. Plugins * may add their methods to this map also. */ - this.api = {version: () => '0.2.1'}; - hasView && (this.api.visualize = this._visualize.bind(this)); + this.api = {}; + Helper.setApi(this.api, 'version', '0.2.1.1', 'Shows construct version'); + hasView && Helper.setApi(this.api, 'visualize', this._visualize.bind(this), 'Turns on/off visualization in browser for current instance (world). Turning visualization off, increases application speed.'); /** * {Boolean} Means that this manager instance doesn't contain view(canvas). diff --git a/client/src/manager/plugins/Config.js b/client/src/manager/plugins/Config.js index de63ebb..9dafbe4 100644 --- a/client/src/manager/plugins/Config.js +++ b/client/src/manager/plugins/Config.js @@ -3,12 +3,13 @@ * * @author flatline */ -const Api = require('./../../share/Config').api; +const Api = require('./../../share/Config').api; +const Helper = require('./../../../../common/src/Helper'); class Config { constructor(manager) { - manager.api.setConfig = Api.set.bind(Api); - manager.api.getConfig = Api.get.bind(Api); + Helper.setApi(manager.api, 'setConfig', Api.set.bind(Api), 'Sets configuration value by name. Namespaces are also supported. Example: \'setConfig(\'organisms.orgMaxOrgs\', 500)\'. Opposite to getConfig()'); + Helper.setApi(manager.api, 'getConfig', Api.get.bind(Api), 'Returns specified config value. First parameter is a namespace (optional) and config name. For example, to get maximum amount of organisms in current instance/world type: man.api.getConfig(\'organisms.orgMaxOrgs\'). Example of organism related configs you may find here (https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). Other configuration parameters are located in files with name Config.js'); } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index ecba4b1..3858d8d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -52,7 +52,11 @@ const Config = { * {Number} Minimum age for cloning. Before that, cloning is impossible. It should * be less then orgAlivePeriod config */ - orgCloneMinAge: 5000, + orgCloneMinAge: 8000, + /** + * {Number} Minimum energy for cloning + */ + orgCloneMinEnergy: 100000, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -63,12 +67,12 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 10000, + orgRainMutationPeriod: 20000, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.01, + orgRainMutationPercent: 0.001, /** * {Boolean} Turn this flag on to give organism a possibility to choose his * own mutations period and percent. false - mean, that these values will be @@ -79,17 +83,17 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 1000, + orgCrossoverPeriod: 20000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 8000, + orgRandomOrgPeriod: 30000, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 30000, + orgAlivePeriod: 25000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -141,7 +145,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 4, + codeYieldPeriod: 10, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. @@ -156,7 +160,7 @@ const Config = { * {Number} Amount of bits, which stores maximum block length. Under block * length we mean maximum amount of lines in one block like if, for,... */ - codeBitsPerBlock: 8, + codeBitsPerBlock: 10, /** * {Number} Amount of iterations between calls to V8 event loop. See * Manager._initLoop(), Manager.run() methods for details. @@ -169,7 +173,7 @@ const Config = { * it's possible for organisms to go outside the limit by inventing new * effective mechanisms of energy obtaining. */ - codeMaxSize: 1000 + codeMaxSize: 300 }; module.exports = Config; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index b7f7abe..f668c7e 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -107,7 +107,7 @@ class Mutator { } _onOrganism(org) { - if (org.iterations % org.mutationPeriod !== 0 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || org.energy < 1) {return} + if (org.iterations % org.mutationPeriod !== 0 || org.iterations < 1 || OConfig.orgRainMutationPeriod === 0 || OConfig.orgRainMutationPercent === 0.0 || org.mutationPeriod === 0 || org.energy < 1) {return} this._mutate(org); } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 8d828b0..8ef9bda 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -241,7 +241,7 @@ class Organism extends Observer { } _updateClone() { - if (this._iterations > OConfig.orgCloneMinAge && this._energy > 0) {this.fire(CLONE, this)} + if (this._iterations > OConfig.orgCloneMinAge && this._energy > OConfig.orgCloneMinEnergy) {this.fire(CLONE, this)} } /** diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index ccbf40a..aba3608 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -17,7 +17,7 @@ const ORG_EVENTS = require('./../../../../src/manager/plugins/organisms/Organi const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); -const RAND_OFFS = 3; +//const RAND_OFFS = 3; const POSID = Helper.posId; // TODO: inherit this class from Configurable @@ -56,7 +56,10 @@ class Organisms extends Configurable { createEmptyOrg(...args) {} constructor(manager) { - super(manager, {Config, cfg: OConfig}, {getAmount: ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)']}); + super(manager, {Config, cfg: OConfig}, { + getAmount : ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)'], + getOrganism: ['_apiGetOrganism', 'Returns organism instance by id or int\'s index in a Queue'] + }); this.organisms = manager.organisms; this.randOrgItem = this.organisms.first; this.positions = manager.positions; @@ -150,7 +153,8 @@ class Organisms extends Configurable { * @return {Organism|null} */ randOrg() { - const offs = Helper.rand(RAND_OFFS) + 1; + //const offs = Helper.rand(RAND_OFFS) + 1; + const offs = Helper.rand(this.organisms.size) + 1; let item = this.randOrgItem; for (let i = 0; i < offs; i++) { @@ -215,13 +219,15 @@ class Organisms extends Configurable { } _crossover(org1, org2) { - this._clone(org1, true); - const orgs = this.organisms; - let child = orgs.last.val; + if (!this._clone(org1, true)) {return false} + let child = this.organisms.last.val; if (child.energy > 0 && org2.energy > 0) { child.changes += (Math.abs(child.vm.crossover(org2.vm)) * Num.MAX_BITS); + return true; } + + return false; } _createPopulation() { @@ -236,12 +242,35 @@ class Organisms extends Configurable { /** * API method, which will be added to Manager.api interface + * @api * @return {Number} Amount of organisms within current Manager */ _apiGetAmount() { return this.parent.organisms.size; } + /** + * Return organism instance by id or it's index in a Queue + * @param {Number|String} index Index or id + * @return {Organism} Organism instance or null + * @api + */ + _apiGetOrganism(index) { + if (Helper.isNumeric(index)) { + return this.organisms.get(index); + } + + let item = this.organisms.first; + let org; + + while (org = item && item.val) { + if (org.id === index) {return org} + item = item.next; + } + + return null; + } + _onDestroyOrg(org) { if (this.randOrgItem === org.item) { if ((this.randOrgItem = org.item.next) === null) { diff --git a/client/src/manager/plugins/organisms/dos/Code2String.js b/client/src/manager/plugins/organisms/dos/Code2String.js index 7cc2bce..139b0f4 100644 --- a/client/src/manager/plugins/organisms/dos/Code2String.js +++ b/client/src/manager/plugins/organisms/dos/Code2String.js @@ -7,6 +7,7 @@ */ const Num = require('./../../../../vm/Num'); const OConfig = require('./../Config'); +const Helper = require('./../../../../../../common/src/Helper'); /** * {Function} Just a shortcuts */ @@ -69,7 +70,7 @@ class Code2String { // // API of the Manager for accessing outside. (e.g. from Console) // - manager.api.formatCode = (code) => this.format(code); + Helper.setApi(manager.api, 'formatCode', (code) => this.format(code), 'Converts byte code array into human readable JavaScript based code. This function is low level. For using it you have to get organism\'s virtual machine reference and then use it\'s code property. For example: man.api.formatCode(man.api.organisms.getOrganism(\'128\').vm.code). This example will find organism with id \'128\' and shows his byte code.'); } destroy() { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index f7f36b6..3e1c007 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -56,8 +56,8 @@ class OperatorsDos extends Operators { constructor(offs, vars, obs) { super(offs, vars, obs); /** - * {Object} These operator handlers should return string, which - * will be added to the final string script for evaluation. + * {Object} These operator handlers should return next script line + * number VM should step to */ this._OPERATORS_CB = [ this.onVar.bind(this), diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index 636e920..c116ac0 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -226,10 +226,12 @@ describe("client/src/organism/OrganismDos", () => { it('Organism should fire CLONE event if enough age', () => { let flag = false; const minAge = OConfig.orgCloneMinAge; + const minEnergy = OConfig.orgCloneMinEnergy; const yieldPeriod = OConfig.codeYieldPeriod; const weights = OConfig.orgOperatorWeights.slice(); const newWeights = [.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1]; OConfig.orgCloneMinAge = 1; + OConfig.orgCloneMinEnergy = 1; OConfig.codeYieldPeriod = 1; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...newWeights); const org1 = new OrganismDos('0', 1, 2, null); @@ -246,7 +248,8 @@ describe("client/src/organism/OrganismDos", () => { expect(flag).toBe(true); org1.destroy(); - OConfig.orgCloneMinAge = minAge; + OConfig.orgCloneMinAge = minAge; + OConfig.orgCloneMinEnergy = minEnergy; OConfig.codeYieldPeriod = yieldPeriod; OConfig.orgOperatorWeights.splice(0, OConfig.orgOperatorWeights.length, ...weights); }) diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index b02b51d..73bcab6 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -18,7 +18,7 @@ const API = { pos9 : ['_pos9', 'Sets chart position in 3x3 grid' ], pos16 : ['_pos16', 'Sets chart position in 4x4 grid' ], active : ['_active', 'Activates/Deactivates chart' ], - on : ['_on', 'Activates/Deactivates chart' ], + on : ['_on', 'Activates/Deactivates chart by name' ], off : ['_off', 'Deactivates chart' ], reset : ['_reset', 'Resets chart data' ], preset : ['_preset', 'Positioning charts according to preset'] diff --git a/common/src/Configurable.js b/common/src/Configurable.js index dd7665c..dd516c9 100644 --- a/common/src/Configurable.js +++ b/common/src/Configurable.js @@ -97,8 +97,7 @@ class Configurable { const isStr = typeof key === 'string'; let desc = isStr && 'No description' || key[1]; - cfg[c] = (isStr && this[key] || this[key[0]]).bind(this); - cfg[c].desc = desc; + Helper.setApi(cfg, c, (isStr && this[key] || this[key[0]]).bind(this), desc); } } diff --git a/common/src/Helper.js b/common/src/Helper.js index 71eeef8..21e8d2d 100644 --- a/common/src/Helper.js +++ b/common/src/Helper.js @@ -63,6 +63,18 @@ class Helper { return el; } + /** + * Sets API function, which may be used by users in Chrome console (in DevTools) + * @param {Object} obj Destination object + * @param {String} name Name of function/property + * @param {Function|*} fn Function or value (if property) + * @param {String} desc Description + */ + static setApi(obj, name, fn, desc = '') { + obj[name] = fn; + Helper.isFunc(fn) && (obj[name].desc = desc); + } + /** * Sets first letter to lower case * @param {String} s From 71ee0a0b531c739a37733ba63a880f402bfb3fa6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Thu, 22 Mar 2018 21:34:14 +0200 Subject: [PATCH 276/291] added console API commends to the README #118 fixed small issue with extra mutations on start added min energy for ability to clone added description to API methods changed version to 0.2.1.1 --- client/src/manager/Manager.js | 5 ++ client/src/manager/plugins/Energy.js | 4 +- client/src/manager/plugins/Stones.js | 62 +++++++++++++++++++ .../manager/plugins/organisms/Organisms.js | 2 - .../plugins/organisms/dos/Organisms.js | 15 ++++- client/src/share/Config.js | 17 ++++- client/src/view/World.js | 3 +- 7 files changed, 100 insertions(+), 8 deletions(-) create mode 100644 client/src/manager/plugins/Stones.js diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index e18ef7b..67acfb0 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -48,6 +48,10 @@ class Manager extends Observer { * and track all world objects */ this.positions = {}; + /** + * {Object} Map of world objects like stones, water,... + */ + this.objects = {}; /** * {Object} This field is used as a container for public API of the Manager. * It may be used in a user console by the Operator of construct. Plugins @@ -193,6 +197,7 @@ class Manager extends Observer { this._world = null; this.api = null; this._codeRuns = 0; + this.objects = null; this.positions = null; this.organisms.destroy(); this.organisms = null; diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 30c7f81..c4dc222 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -39,7 +39,7 @@ class Energy { _addEnergyBlock() { const width = Config.worldWidth; const height = Config.worldHeight; - const color = Helper.rand(Organism.getMaxColors()); + const color = Organism.getColor(Config.worldEnergyColorIndex); let block = Config.worldEnergyBlockSize; const world = this._manager.world; let x = Helper.rand(width); @@ -49,7 +49,7 @@ class Energy { x = x + Helper.rand(3) - 1; y = y + Helper.rand(3) - 1; if (x < 0 || x >= width || y < 0 || y >= height) {return} - if (world.isFree(x, y)) {world.setDot(x, y, Organism.getColor(color))} + if (world.isFree(x, y)) {world.setDot(x, y, color)} } } diff --git a/client/src/manager/plugins/Stones.js b/client/src/manager/plugins/Stones.js new file mode 100644 index 0000000..f2dfae4 --- /dev/null +++ b/client/src/manager/plugins/Stones.js @@ -0,0 +1,62 @@ +/** + * Manager's plugin, which add stones to the world + * + * @author flatline + */ +const Helper = require('./../../../../common/src/Helper'); +const Config = require('./../../share/Config').Config; +const Organism = require('./../../manager/plugins/organisms/Organism').Organism; +const OBJECT_TYPES = require('./../../view/World').OBJECT_TYPES; + +const STONE_BLOCK_SIZE = 300; +const POSID = Helper.posId; +// +// We have to add stone type to global types storage +// +OBJECT_TYPES.TYPE_STONE = Object.keys(OBJECT_TYPES).length; + +class Stones { + constructor(manager) { + this._manager = manager; + this._onLoopCb = this._onLoop.bind(this); + + Helper.override(manager, 'onLoop', this._onLoopCb); + } + + destroy() { + Helper.unoverride(this._manager, 'onLoop', this._onLoopCb); + this._manager = null; + this._onLoopCb = null; + } + + _onLoop(counter) { + if (counter > 1 || Config.worldStonesAmount === 0) {return} + + const stones = Config.worldStonesAmount; + for (let i = 0; i < stones; i++) { + this._addStoneBlock(); + } + } + + _addStoneBlock() { + const width = Config.worldWidth; + const height = Config.worldHeight; + const color = Organism.getColor(Config.worldStoneColorIndex); + const man = this._manager; + const world = man.world; + const stone = OBJECT_TYPES.TYPE_STONE; + let x = Helper.rand(width); + let y = Helper.rand(height); + + for (let i = 0; i < STONE_BLOCK_SIZE; i++) { + x = x + Helper.rand(3) - 1; + y = y + Helper.rand(3) - 1; + if (x < 0 || x >= width || y < 0 || y >= height) {return} + if (world.isFree(x, y)) { + world.setDot(x, y, color) && (man.objects[POSID(x, y)] = stone); + } + } + } +} + +module.exports = Stones; \ No newline at end of file diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index aba3608..597bc08 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -17,7 +17,6 @@ const ORG_EVENTS = require('./../../../../src/manager/plugins/organisms/Organi const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); -//const RAND_OFFS = 3; const POSID = Helper.posId; // TODO: inherit this class from Configurable @@ -153,7 +152,6 @@ class Organisms extends Configurable { * @return {Organism|null} */ randOrg() { - //const offs = Helper.rand(RAND_OFFS) + 1; const offs = Helper.rand(this.organisms.size) + 1; let item = this.randOrgItem; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 26c0df1..7e84c09 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -23,6 +23,7 @@ const DIR = require('./../../../../../../common/src/Directions').DI const EMPTY = 0; const ENERGY = 1; const ORGANISM = 2; +const OBJECT = 3; /** * {Function} Is created to speed up this function call. constants are run * much faster, then Helper.normalize() @@ -136,6 +137,13 @@ class Organisms extends BaseOrganisms { [x, y] = NORMALIZE_NO_DIR(x, y); const posId = POSID(x, y); // + // World object found. We can't eat objects + // + if (typeof(this.parent.objects[posId]) !== 'undefined') { + ret.ret = 0; + return; + } + // // Energy found // if (typeof(positions[posId]) === 'undefined') { @@ -211,9 +219,12 @@ class Organisms extends BaseOrganisms { } _onCheckAt(x, y, ret) { - [x, y] = NORMALIZE_NO_DIR(x, y); + const posId = POSID(x, y); + [x, y] = NORMALIZE_NO_DIR(x, y); - if (typeof(this.parent.positions[POSID(x, y)]) === 'undefined') { + if (typeof(this.parent.objects[posId]) !== 'undefined') { + ret.ret = OBJECT + this.parent.objects[posId]; + } else if (typeof(this.parent.positions[posId]) === 'undefined') { ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; } else { ret.ret = ORGANISM; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 63f07c2..41e6fbd 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -39,6 +39,7 @@ ClientConfig.init({ 'Config', 'client/Client', 'Energy', + 'Stones', 'status/console/Console', IS_NODE_JS ? '' : 'status/charts/Charts', 'ips/Ips', @@ -72,9 +73,14 @@ ClientConfig.init({ */ worldEnergyCheckPeriod: 5000, /** - * {Number} size of one clever energy block in dots. + * {Number} size of one clever energy block in dots */ worldEnergyBlockSize: 200, + /** + * {Number} Index of energy color. Starts from 0. Ends with 4000. See Organism.MAX_COLORS + * constant for details + */ + worldEnergyColorIndex: 0, /** * {Number} Percent from all energy in a world until clever energy will be added. * After this value clever energy will be stopped to add until it's amount will @@ -88,6 +94,15 @@ ClientConfig.init({ * world again). */ worldEnergyMinPercent: .0001, + /** + * {Number} Amount of random stones in a world + */ + worldStonesAmount: 600, + /** + * {Number} Color index for stones in a world. See Organism.MAX_COLORS + * constant for details + */ + worldStoneColorIndex: 1800, /** * {Number} Zoom speed 0..1 */ diff --git a/client/src/view/World.js b/client/src/view/World.js index 0c7e880..6b8d43a 100644 --- a/client/src/view/World.js +++ b/client/src/view/World.js @@ -30,6 +30,7 @@ const WEVENTS = { * The same like this.getDot(x, y) === 0 */ const FREE_DOT_ATTEMPTS = 100; +const OBJECT_TYPES = {}; class World extends Observer { constructor (width, height) { @@ -118,4 +119,4 @@ class World extends Observer { } } -module.exports = {World, EVENTS: WEVENTS}; \ No newline at end of file +module.exports = {World, EVENTS: WEVENTS, OBJECT_TYPES}; \ No newline at end of file From b766b0b583b1f9e52868fab7f838b59df3cdc2d6 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Mar 2018 22:23:24 +0200 Subject: [PATCH 277/291] added oenergy chart removed unused console statistics parameters --- .../src/manager/plugins/organisms/Config.js | 24 +++++++++---------- .../manager/plugins/organisms/Organisms.js | 5 ++-- .../plugins/organisms/dos/Organisms.js | 12 +++++----- client/src/manager/plugins/status/Status.js | 19 ++++++++++----- .../manager/plugins/status/charts/Charts.js | 9 +++---- .../manager/plugins/status/charts/Config.js | 2 +- .../manager/plugins/status/console/Console.js | 5 ++-- client/src/share/Config.js | 10 ++++---- 8 files changed, 47 insertions(+), 39 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 3858d8d..1347f22 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. */ orgOperatorWeights: [ - .0001, .0001, .000001, .000000001, .00001, // var, const, if, loop, operator, - .00001, .02, .02, .02, .02, // lookAt, eatLeft, eatRight, eatUp, eatDown, - .2, .2, .2, .2, // stepLeft, stepRight, stepUp, stepDown, - .0001, .0001, // fromMem, toMem, - .00001, .00001, // myX, myY, - .0001, .0001, .0001, .0001 // checkLeft, checkRight, checkUp, checkDown + .001, .001, .00001, .00000001, .0001, // var, const, if, loop, operator, + .0001, .2, .2, .2, .2, // lookAt, eatLeft, eatRight, eatUp, eatDown, + 2, 2, 2, 2, // stepLeft, stepRight, stepUp, stepDown, + .001, .001, // fromMem, toMem, + .0001, .0001, // myX, myY, + .001, .001, .001, .001 // checkLeft, checkRight, checkUp, checkDown ], /** * {Array} Probabilities which used, when mutator decides what to do: @@ -67,7 +67,7 @@ const Config = { * do mutations according to orgRainMutationPercent config. If 0, then * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 20000, + orgRainMutationPeriod: 9500, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) @@ -83,17 +83,17 @@ const Config = { * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 20000, + orgCrossoverPeriod: 10000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 30000, + orgRandomOrgPeriod: 20000, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 25000, + orgAlivePeriod: 10000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -119,11 +119,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 500, + orgMaxOrgs: 400, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 500, + orgStartAmount: 400, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 597bc08..047a1bf 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -60,6 +60,7 @@ class Organisms extends Configurable { getOrganism: ['_apiGetOrganism', 'Returns organism instance by id or int\'s index in a Queue'] }); this.organisms = manager.organisms; + this.objects = manager.objects; this.randOrgItem = this.organisms.first; this.positions = manager.positions; this.world = manager.world; @@ -171,8 +172,8 @@ class Organisms extends Configurable { * @param {Number} stamp Time stamp of current iteration */ _onIteration(counter, stamp) { - let item = this.organisms.first; - let org; + let item = this.organisms.first; + let org; while (org = item && item.val) { org.run(); diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 7e84c09..bf7a71b 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -128,7 +128,6 @@ class Organisms extends BaseOrganisms { } _onEat(org, x, y, ret) { - const positions = this.positions; // // Amount of eat energy depends on organism size. Small organisms // eat less, big - more @@ -139,14 +138,14 @@ class Organisms extends BaseOrganisms { // // World object found. We can't eat objects // - if (typeof(this.parent.objects[posId]) !== 'undefined') { + if (typeof(this.objects[posId]) !== 'undefined') { ret.ret = 0; return; } // // Energy found // - if (typeof(positions[posId]) === 'undefined') { + if (typeof(this.positions[posId]) === 'undefined') { if (eat >= 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); @@ -159,7 +158,7 @@ class Organisms extends BaseOrganisms { // Organism found // } else { - const victimOrg = positions[posId]; + const victimOrg = this.positions[posId]; ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); if (victimOrg.energy <= ret.ret) { this.parent.fire(EVENTS.KILL_EAT, victimOrg); @@ -171,6 +170,7 @@ class Organisms extends BaseOrganisms { // victimOrg.destroy(); } else { + this.parent.fire(EVENTS.EAT_ORG, victimOrg, ret.ret); victimOrg.energy -= ret.ret; } } @@ -222,8 +222,8 @@ class Organisms extends BaseOrganisms { const posId = POSID(x, y); [x, y] = NORMALIZE_NO_DIR(x, y); - if (typeof(this.parent.objects[posId]) !== 'undefined') { - ret.ret = OBJECT + this.parent.objects[posId]; + if (typeof(this.objects[posId]) !== 'undefined') { + ret.ret = OBJECT + this.objects[posId]; } else if (typeof(this.parent.positions[posId]) === 'undefined') { ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; } else { diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index fae69d8..bbb013c 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -19,7 +19,6 @@ const Helper = require('./../../../../../common/src/Helper'); const EVENTS = require('./../../../share/Events').EVENTS; const Configurable = require('./../../../../../common/src/Configurable'); const Config = require('./../../../share/Config').Config; -const OConfig = require('./../../../manager/plugins/organisms/Config'); class Status extends Configurable { static _toFixed(val, fixed) { @@ -38,7 +37,7 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, ips :0, orgs :0, energy :0, penergy :0, eenergy:0, wenergy:0, wenergyup:true, changes:0, fit:0, age:0, code:0, + lps :0, ips :0, orgs :0, energy :0, oenergy :0, eenergy:0, wenergy:0, wenergyup:true, changes:0, fit:0, age:0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killclone:0 }; this._stamp = 0; @@ -64,6 +63,7 @@ class Status extends Configurable { this._onLoopCb = this._onLoop.bind(this); this._onIpsCb = this._onIps.bind(this); this._onEatEnergyCb = this._onEatEnergy.bind(this); + this._onEatOrgCb = this._onEatOrg.bind(this); this._onPutEnergyCb = this._onPutEnergy.bind(this); this._onKillOrgCb = this._onKillOrg.bind(this); this._onKillEnergyCb = this._onKillHandlerOrg.bind(this, 1); @@ -80,6 +80,7 @@ class Status extends Configurable { Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.IPS, this._onIpsCb); manager.on(EVENTS.EAT_ENERGY, this._onEatEnergyCb); + manager.on(EVENTS.EAT_ORG, this._onEatOrgCb); manager.on(EVENTS.PUT_ENERGY, this._onPutEnergyCb); manager.on(EVENTS.KILL, this._onKillOrgCb); manager.on(EVENTS.KILL_TOUR, this._onKillTourCb); @@ -111,6 +112,7 @@ class Status extends Configurable { man.off(EVENTS.KILL_TOUR, this._onKillTourCb); man.off(EVENTS.KILL, this._onKillOrgCb); man.off(EVENTS.PUT_ENERGY, this._onPutEnergyCb); + man.off(EVENTS.EAT_ORG, this._onEatOrgCb); man.off(EVENTS.EAT_ENERGY, this._onEatEnergyCb); man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(man, 'onLoop', this._onLoopCb); @@ -120,6 +122,7 @@ class Status extends Configurable { this._onKillOrgCb = null; this._onKillTourCb = null; this._onPutEnergyCb = null; + this._onEatOrgCb = null; this._onEatEnergyCb = null; this._onKillCloneCb = null; this._onKillInCb = null; @@ -155,7 +158,6 @@ class Status extends Configurable { item = item.next; } - this._pickEnergy = ((energy - startEnergy) / iterations) / size; this._energy = energy / size; this._changes = changes / size; this._fitness = fitness / size; @@ -174,11 +176,11 @@ class Status extends Configurable { this._onBeforeLoop(orgs); - status.ips = fix(this._ips / this._ipsTimes * OConfig.codeYieldPeriod, 2); + status.ips = fix(this._ips / this._ipsTimes, 2); status.lps = fix((this.parent.codeRuns - this._codeRuns) / ((stamp - this._stamp) / 1000), 0); status.orgs = orgAmount; status.energy = fix(this._energy, 2); - status.penergy = fix(this._pickEnergy * 1000, 2); + status.oenergy = fix(this._pickEnergy / orgAmount, 2); status.eenergy = fix(this._eatEnergy / orgAmount, 2); status.puenergy = fix(this._putEnergy / orgAmount, 2); status.changes = +(this._changes).toFixed(1); @@ -230,6 +232,10 @@ class Status extends Configurable { this._eatEnergy += eat; } + _onEatOrg(org, eat) { + this._pickEnergy += eat; + } + /** * Calculates putting of energy by organisms to the world * @param {Number} put Amount of put energy @@ -245,8 +251,9 @@ class Status extends Configurable { this._kill[0] ++; } - _onKillHandlerOrg(index) { + _onKillHandlerOrg(index, org) { this._kill[index]++; + index === 4 && (this._pickEnergy += org.energy); } _onWorldEnergy(percent) { diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index 73bcab6..ccccb0f 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -47,7 +47,7 @@ const PRESETS = { orgs : '0-1|16', energy : '0-2|16', eenergy : '0-3|16', - penergy : '1-0|16', + oenergy : '1-0|16', changes : '1-1|16', age : '1-2|16', code : '1-3|16', @@ -71,7 +71,7 @@ const PRESETS = { lps : 'topleft', energy : 'downleft', eenergy : 'topright', - penergy : 'downright' + oenergy : 'downright' } }; @@ -108,7 +108,7 @@ class Charts extends Status { ips : new Chart('IPS - Iterations Per Second', Config.charts.ips), orgs : new Chart('Amount of organisms', Config.charts.orgs), energy : new Chart('Average organism energy', Config.charts.energy), - penergy : new Chart('Average organism\'s picked energy (all)', Config.charts.penergy), + oenergy : new Chart('Average organism\'s eat energy from other organisms', Config.charts.oenergy), eenergy : new Chart('Average organism\'s picked energy (energy only)', Config.charts.eenergy), puenergy : new Chart('Average organism\'s put energy to the world', Config.charts.puenergy), changes : new Chart('Average organism\'s changes (Mutations)', Config.charts.changes), @@ -165,6 +165,7 @@ class Charts extends Status { const conns = `${active[0] ? '^' : ''}${active[1] ? '>' : ''}${active[2] ? 'v' : ''}${active[3] ? '<' : ''}`; const ips = `ips:${status.ips}`; const enrg = `enrg:${status.eenergy}`; + const onrg = `onrg:${status.oenergy}`; const wnrg = `wnrg:${status.wenergy}`; const wnrgup = status.wenergyup ? '\u2191' : '\u2193'; const code = `cod:${status.code}`; @@ -173,7 +174,7 @@ class Charts extends Status { const kilo = `kilo:${status.killeat}`; const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${wnrgup} ${enrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${wnrgup} ${enrg} ${onrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; } /** diff --git a/client/src/manager/plugins/status/charts/Config.js b/client/src/manager/plugins/status/charts/Config.js index 3facf59..00871a7 100644 --- a/client/src/manager/plugins/status/charts/Config.js +++ b/client/src/manager/plugins/status/charts/Config.js @@ -25,7 +25,7 @@ const Config = { killout : {pos: 'topright', active: false, transparent: 0.8}, energy : {pos: 'downright', active: false, transparent: 0.8}, orgs : {pos: '0-0|16', active: false, transparent: 0.8}, - penergy : {pos: '0-1|16', active: false, transparent: 0.8}, + oenergy : {pos: '0-1|16', active: false, transparent: 0.8}, eenergy : {pos: '0-2|16', active: false, transparent: 0.8}, puenergy : {pos: '0-3|16', active: false, transparent: 0.8}, fit : {pos: '1-0|16', active: false, transparent: 0.8}, diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 37aef97..80865fc 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -48,17 +48,16 @@ class Console extends Status { const slps = format(status.lps, 'lps', 14); const sorgs = format(orgs, 'org', 10); const senergy = format(status.energy, 'nrg', 19); - const spenergy = format(status.penergy, 'pnrg', 15); + const spenergy = format(status.oenergy, 'onrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); const wenergy = format(status.wenergy + (status.wenergyup ? '\u2191' : '\u2193'), 'wnrg', 14); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); - const sfit = format(status.fit, 'fit', 13); const sage = format(status.age, 'age', 11); const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${wenergy}${skill}${schanges}${sfit}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${wenergy}${skill}${schanges}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 41e6fbd..9434af8 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 / 2, + worldWidth: 1920, /** * {Number} World height */ - worldHeight: 1080 / 2, + worldHeight: 1080, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -66,7 +66,7 @@ ClientConfig.init({ * coordinate (height). It actual only for one instance mode (no distributed * calculations). */ - worldCyclical: false, + worldCyclical: true, /** * {Number} An amount of iteration, after which we have to check world energy * percent. May be 0 if you want to disable energy generation @@ -93,11 +93,11 @@ ClientConfig.init({ * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldEnergyMinPercent: .0001, + worldEnergyMinPercent: .0002, /** * {Number} Amount of random stones in a world */ - worldStonesAmount: 600, + worldStonesAmount: 4000, /** * {Number} Color index for stones in a world. See Organism.MAX_COLORS * constant for details From 31a844d0ef68e2f60512588ba1d905edc6983f19 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 23 Mar 2018 23:04:42 +0200 Subject: [PATCH 278/291] added commands #118 --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 73e33a6..8c5723b 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,10 @@ As an administrator, you may affect the system by command line API. For instance - charts namespace - `man.api.charts`. This namespace is related to statistics in charts. There are many parameters like average code size, organisms amount, amount of picked energy and so on. See details [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js) in charts property. You may show and hide different charts on a canvas, locate them and reset any time you need: - `man.api.charts.on([[name:String = undefined[, show:Boolean = true]])` - shows chart(s) by name. List of all available names you may find [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). Example: `man.api.charts.on('energy')` - will show chart of average organism energy at the moment. Calling this method without parameters shows all available charts. Calling this method with only one string parameter shows specified chart. Calling this method with two parameters shows/hides specified chart depending on second Boolean parameter. Example: `man.api.charts.on()` - shows all charts. `man.api.charts.on('energy')` - shows energy chart only. `man.api.charts.on('energy', false)` - hides energy chart only. - `man.api.charts.off(name:String = undefined)` - opposite to `on()`. Hides specified or all charts (without parameters) from the canvas. - - `man.api.charts.pos(String, String)` - Locates chart according to specified position. Available positions are: `full`, `top`, `down`, `left`, `right`, `topleft`, `downleft`, `topright`, `downright`. Example: `man.api.charts.pos('code', 'full')` - shows `code` trend chart on full screen. All available chart names are [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). - + - `man.api.charts.pos(name:String, pos:String)` - Locates chart according to specified position. Available positions are: `full`, `top`, `down`, `left`, `right`, `topleft`, `downleft`, `topright`, `downright`. Example: `man.api.charts.pos('code', 'full')` - shows `code` trend chart on full screen. All available chart names are [here](https://github.com/tmptrash/construct/blob/master/client/src/manager/plugins/status/charts/Config.js). + - `man.api.charts.pos9(name:String, x:Number, y:Number)` - The same like `pos()`, but with chart coordinates in 3x3 grid. For example: `man.api.charts.pos9('energy', 0, 2)` - will positioning energy chart at the location `x:0, y:2`. + - `man.api.charts.pos16(name:String, x:Number, y:Number)` - The same like `pos9()`, but for grid 4x4. + - `man.api.charts.transparent(name:String, val:Number)` - Sets chart transparency. `val` should be between `0..1`. `val` parameter is optional. In this case all charts will have same transparency. Note: to improve speed, type `man.api.visualize(false)` in Chrome's devtool console during application run ___ P.S. If you are a `ES6 js developer` | `Canvas 2D developer` | `Node.js developer` | you just a - join us! From 9dbc2e247e19e5e4483d59f1bd722ad58e6bca48 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 24 Mar 2018 14:24:27 +0200 Subject: [PATCH 279/291] small optimizations --- .../src/manager/plugins/organisms/Config.js | 4 ++-- .../src/manager/plugins/organisms/Organism.js | 22 ++++++++++--------- .../plugins/organisms/dos/Organisms.js | 4 ++-- client/src/share/Config.js | 6 ++--- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 1347f22..ad7543b 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -119,11 +119,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 400, + orgMaxOrgs: 20000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 400, + orgStartAmount: 10000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 8ef9bda..3d86e85 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -25,7 +25,8 @@ const ORG_EVENTS = { ITERATION }; -const MAX_COLORS = 4000; +const MAX_COLORS = 4000; +const UPDATE_COLOR_PERIOD = 50; class Organism extends Observer { /** @@ -81,14 +82,15 @@ class Organism extends Observer { if (parent === null) {this._create()} else {this._clone(parent)} - this._id = id; - this._x = x; - this._y = y; - this._iterations = -1; - this._changes = 0; - this._item = item; - this._maxEnergy = 0; - this._fnId = 0; + this._id = id; + this._x = x; + this._y = y; + this._iterations = -1; + this._changes = 0; + this._item = item; + this._maxEnergy = 0; + this._energyChanges = 0; + this._fnId = 0; } get id() {return this._id} @@ -110,7 +112,7 @@ class Organism extends Observer { set y(newY) {this._y = newY} set mutationPeriod(m) {this._mutationPeriod = m} set mutationPercent(p) {this._mutationPercent = p} - set energy(e) {if (this.vm !== null) { this._energy = e; this._updateColor()}} + set energy(e) {if (this.vm !== null) { this._energy = e; ++this._energyChanges % UPDATE_COLOR_PERIOD === 0 && this._updateColor()}} set startEnergy(e) {this._startEnergy = e} set changes(c) {this._changes = c} set maxEnergy(e) {this._maxEnergy = e} diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index bf7a71b..f5842b3 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -224,8 +224,8 @@ class Organisms extends BaseOrganisms { if (typeof(this.objects[posId]) !== 'undefined') { ret.ret = OBJECT + this.objects[posId]; - } else if (typeof(this.parent.positions[posId]) === 'undefined') { - ret.ret = this.parent.world.getDot(x, y) > 0 ? ENERGY : EMPTY; + } else if (typeof(this.positions[posId]) === 'undefined') { + ret.ret = this.world.getDot(x, y) > 0 ? ENERGY : EMPTY; } else { ret.ret = ORGANISM; } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 9434af8..5f8dbdf 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920, + worldWidth: 1920 / 2, /** * {Number} World height */ - worldHeight: 1080, + worldHeight: 1080 / 2, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -97,7 +97,7 @@ ClientConfig.init({ /** * {Number} Amount of random stones in a world */ - worldStonesAmount: 4000, + worldStonesAmount: 1500, /** * {Number} Color index for stones in a world. See Organism.MAX_COLORS * constant for details From 10eaf40e967b676cc137d278f3bfa159b29e9a46 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 27 Mar 2018 18:00:22 +0300 Subject: [PATCH 280/291] speed optimizations of DOS VM added orgKilOnClone config fixed an issue with stuck of evolution fixed an issue with incorrect energy calculation stones amount is now in percents (config) --- client/src/manager/plugins/Energy.js | 4 ++- client/src/manager/plugins/Stones.js | 20 +++++++---- .../src/manager/plugins/organisms/Config.js | 33 +++++++++++-------- .../src/manager/plugins/organisms/Mutator.js | 4 +-- .../manager/plugins/organisms/Organisms.js | 6 ++-- .../plugins/organisms/dos/Operators.js | 24 ++++++++++---- .../plugins/organisms/dos/Organisms.js | 32 +++++++++--------- client/src/share/Config.js | 11 ++++--- 8 files changed, 81 insertions(+), 53 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index c4dc222..6ef17db 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -59,10 +59,12 @@ class Energy { const width = Config.worldWidth; const height = Config.worldHeight; const poses = this._manager.positions; + const objs = this._manager.objects; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - if (typeof poses[POSID(x, y)] === 'undefined') {energy += world.getDot(x, y)} + const posId = POSID(x, y); + if (typeof poses[posId] === 'undefined' && typeof objs[posId] === 'undefined') {energy += world.getDot(x, y)} } } diff --git a/client/src/manager/plugins/Stones.js b/client/src/manager/plugins/Stones.js index f2dfae4..7697fe4 100644 --- a/client/src/manager/plugins/Stones.js +++ b/client/src/manager/plugins/Stones.js @@ -30,15 +30,16 @@ class Stones { } _onLoop(counter) { - if (counter > 1 || Config.worldStonesAmount === 0) {return} + if (counter > 1 || Config.worldStonesPercent === .0) {return} - const stones = Config.worldStonesAmount; - for (let i = 0; i < stones; i++) { - this._addStoneBlock(); + const stones = Config.worldStonesPercent * Config.worldWidth * Config.worldHeight; + let amount = 0; + while (amount < stones) { + amount = this._addStoneBlock(amount, stones); } } - _addStoneBlock() { + _addStoneBlock(amount, stones) { const width = Config.worldWidth; const height = Config.worldHeight; const color = Organism.getColor(Config.worldStoneColorIndex); @@ -51,11 +52,16 @@ class Stones { for (let i = 0; i < STONE_BLOCK_SIZE; i++) { x = x + Helper.rand(3) - 1; y = y + Helper.rand(3) - 1; - if (x < 0 || x >= width || y < 0 || y >= height) {return} + if (x < 0 || x >= width || y < 0 || y >= height) {return amount} if (world.isFree(x, y)) { - world.setDot(x, y, color) && (man.objects[POSID(x, y)] = stone); + if (world.setDot(x, y, color)) { + man.objects[POSID(x, y)] = stone; + if (++amount >= stones) {return amount} + } } } + + return amount; } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index ad7543b..148c4cc 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -47,12 +47,19 @@ const Config = { * {Boolean} If turned on, then organism will be responsible for changing * mutations probabilities. Otherwise these probabilities will be constant */ - orgMutationPerOrg: false, + orgMutationProbsPerOrg: true, /** * {Number} Minimum age for cloning. Before that, cloning is impossible. It should * be less then orgAlivePeriod config */ - orgCloneMinAge: 8000, + orgCloneMinAge: 200, + /** + * {Boolean} If true, then random organism will be killed after new one has + * cloned and amount of organisms is greater then orgMaxOrgs config. false + * mean, that new organism will not be cloned, if amount of organisms is >= + * orgMaxOrgs config. + */ + orgKillOnClone: false, /** * {Number} Minimum energy for cloning */ @@ -65,35 +72,35 @@ const Config = { /** * {Number} Amount of iterations within organism's life loop, after that we * do mutations according to orgRainMutationPercent config. If 0, then - * mutations will be disabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD + * mutations wilsabled. Should be less then ORGANISM_MAX_MUTATION_PERIOD */ - orgRainMutationPeriod: 9500, + orgRainMutationPeriod: 100, /** * {Number} Percent of mutations from code size. 0 is a possible value if * we want to disable mutations. Should be less then 1.0 (1.0 === 100%) */ - orgRainMutationPercent: 0.001, + orgRainMutationPercent: 0.01, /** * {Boolean} Turn this flag on to give organism a possibility to choose his * own mutations period and percent. false - mean, that these values will be * constant for all organisms */ - orgRainPerOrg: false, + orgRainPerOrg: true, /** * {Number} Amount of iterations, after which crossover will be applied * to random organisms. May be set to 0 to turn crossover off */ - orgCrossoverPeriod: 10000, + orgCrossoverPeriod: 4000, /** * {Number} Period of iterations for creation of random organisms. Set it to 0 * to turn off this feature */ - orgRandomOrgPeriod: 20000, + orgRandomOrgPeriod: 5000, /** * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 10000, + orgAlivePeriod: 500, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, @@ -119,17 +126,17 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 20000, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 10000, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 10000000, + orgStartEnergy: 1000000, /** * {Number} Amount of bits for storing a numeric constant inside byte code */ @@ -145,7 +152,7 @@ const Config = { * organism without interruption by one VM. Set this value to value bigger * then codeMaxSize, then entire code of organism will be run */ - codeYieldPeriod: 10, + codeYieldPeriod: 5, /** * {Number} Amount of bits per one variable. It affects maximum value, * which this variable may contain. This value shouldn't be less then 2. diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index f668c7e..65de19c 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -54,7 +54,7 @@ class Mutator { static _onMutationPeriod(org) { if (!OConfig.orgRainPerOrg) {return} - org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod); + org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod - 1) + 1; org.changes++; } @@ -65,7 +65,7 @@ class Mutator { } static _onProbs(org) { - if (!OConfig.orgMutationPerOrg) {return} + if (!OConfig.orgMutationProbsPerOrg) {return} org.mutationProbs[Helper.rand(org.mutationProbs.length)] = Helper.rand(OConfig.ORG_MUTATION_PROBS_MAX_VAL) || 1; org.changes++; } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 047a1bf..7bb5954 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -92,7 +92,7 @@ class Organisms extends Configurable { } /** - * Is called at the end of run() method + * Is called at the end of run() method. Updates maxEnergy value for population * @param {Organism} org Current organism */ onOrganism(org) { @@ -309,7 +309,9 @@ class Organisms extends Configurable { // organisms before cloning. They should kill each other to have a possibility // to clone them. // - this.organisms.size < OConfig.orgMaxOrgs && this._clone(org); + if (org.energy < OConfig.orgCloneMinEnergy) {return} + if (OConfig.orgKillOnClone && this.organisms.size >= OConfig.orgMaxOrgs) {this.randOrg().destroy()} + if (this.organisms.size < OConfig.orgMaxOrgs) {this._clone(org)} } _killInTour() { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 3e1c007..527188b 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -251,13 +251,23 @@ class OperatorsDos extends Operators { onMyX(num, line, org) {this.vars[Num.getVar0(num)] = org.x; return ++line} onMyY(num, line, org) {this.vars[Num.getVar0(num)] = org.y; return ++line} - onCheckLeft(num, line, org) {return this._checkAt(num, line, org.x - 1, org.y)} - onCheckRight(num, line, org) {return this._checkAt(num, line, org.x + 1, org.y)} - onCheckUp(num, line, org) {return this._checkAt(num, line, org.x, org.y - 1)} - onCheckDown(num, line, org) {return this._checkAt(num, line, org.x, org.y + 1)} - - _checkAt(num, line, x, y) { - this.obs.fire(EVENTS.CHECK_AT, x, y, this._ret); + onCheckLeft(num, line, org) { + this.obs.fire(EVENTS.CHECK_AT, org.x - 1, org.y, this._ret); + this.vars[Num.getVar0(num)] = this._ret.ret; + return ++line; + } + onCheckRight(num, line, org) { + this.obs.fire(EVENTS.CHECK_AT, org.x + 1, org.y, this._ret); + this.vars[Num.getVar0(num)] = this._ret.ret; + return ++line; + } + onCheckUp(num, line, org) { + this.obs.fire(EVENTS.CHECK_AT, org.x, org.y - 1, this._ret); + this.vars[Num.getVar0(num)] = this._ret.ret; + return ++line; + } + onCheckDown(num, line, org) { + this.obs.fire(EVENTS.CHECK_AT, org.x, org.y + 1, this._ret); this.vars[Num.getVar0(num)] = this._ret.ret; return ++line; } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index f5842b3..a3b71fb 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -145,7 +145,8 @@ class Organisms extends BaseOrganisms { // // Energy found // - if (typeof(this.positions[posId]) === 'undefined') { + const victimOrg = this.positions[posId]; + if (typeof victimOrg === 'undefined') { if (eat >= 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); @@ -154,25 +155,24 @@ class Organisms extends BaseOrganisms { this.world.setDot(x, y, (((-eat + .5) << 0) >>> 0) + this.world.getDot(x, y)); this.parent.fire(EVENTS.PUT_ENERGY, -eat); } + return; + } // // Organism found // + ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); + if (victimOrg.energy <= ret.ret) { + this.parent.fire(EVENTS.KILL_EAT, victimOrg); + // + // IMPORTANT: + // We have to do destroy here, to have a possibility for current + // (winner) organism to clone himself after eating other organism. + // This is how organisms compete for an ability to clone + // + victimOrg.destroy(); } else { - const victimOrg = this.positions[posId]; - ret.ret = eat < 0 ? 0 : (eat > victimOrg.energy ? victimOrg.energy : eat); - if (victimOrg.energy <= ret.ret) { - this.parent.fire(EVENTS.KILL_EAT, victimOrg); - // - // IMPORTANT: - // We have to do destroy here, to have a possibility for current - // (winner) organism to clone himself after eating other organism. - // This is how organisms compete for an ability to clone - // - victimOrg.destroy(); - } else { - this.parent.fire(EVENTS.EAT_ORG, victimOrg, ret.ret); - victimOrg.energy -= ret.ret; - } + this.parent.fire(EVENTS.EAT_ORG, victimOrg, ret.ret); + victimOrg.energy -= ret.ret; } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 5f8dbdf..97044b1 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 / 2, + worldWidth: 1920 / 4, /** * {Number} World height */ - worldHeight: 1080 / 2, + worldHeight: 1080 / 4, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -75,7 +75,7 @@ ClientConfig.init({ /** * {Number} size of one clever energy block in dots */ - worldEnergyBlockSize: 200, + worldEnergyBlockSize: 20, /** * {Number} Index of energy color. Starts from 0. Ends with 4000. See Organism.MAX_COLORS * constant for details @@ -95,9 +95,10 @@ ClientConfig.init({ */ worldEnergyMinPercent: .0002, /** - * {Number} Amount of random stones in a world + * {Number} Percent of stones in a world. Percent from world size: + * stoneAmount = worldStonesPercent * worldWidth * worldHeight */ - worldStonesAmount: 1500, + worldStonesPercent: .1, /** * {Number} Color index for stones in a world. See Organism.MAX_COLORS * constant for details From d63d85fa77ac3c984db5f68edbdb161248ee9f13 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 28 Mar 2018 00:36:01 +0300 Subject: [PATCH 281/291] updated energy calculation mechanism --- client/src/manager/plugins/Energy.js | 37 +++++++++++-------- client/src/manager/plugins/status/Status.js | 12 +----- .../manager/plugins/status/charts/Charts.js | 3 +- .../manager/plugins/status/console/Console.js | 3 +- client/src/share/Config.js | 10 ++--- 5 files changed, 29 insertions(+), 36 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 6ef17db..935af0b 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -13,7 +13,6 @@ const POSID = Helper.posId; class Energy { constructor(manager) { this._manager = manager; - this._cleverActive = true; this._onIterationCb = this._onIteration.bind(this); Helper.override(manager, 'onIteration', this._onIterationCb); @@ -26,17 +25,18 @@ class Energy { } _onIteration(counter) { - this._cleverActive && this._addEnergyBlock(); - if (Config.worldEnergyCheckPeriod === 0 || counter % Config.worldEnergyCheckPeriod !== 0) {return} - const energy = this._getEnergyPercent(); + let energy = this._getEnergyPercent(); + this._manager.fire(EVENTS.WORLD_ENERGY, energy); - if (energy < Config.worldEnergyMinPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = true)} - else if (energy > Config.worldEnergyMaxPercent) {this._manager.fire(EVENTS.WORLD_ENERGY_UP, this._cleverActive = false)} + if (energy > Config.worldEnergyMinPercent) {return} + const maxEnergy = Config.worldEnergyMaxPercent * Config.worldWidth * Config.worldHeight; + let amount = 0; + while ((amount = this._addEnergyBlock(amount, maxEnergy)) < maxEnergy) {} } - _addEnergyBlock() { + _addEnergyBlock(amount, maxEnergy) { const width = Config.worldWidth; const height = Config.worldHeight; const color = Organism.getColor(Config.worldEnergyColorIndex); @@ -48,27 +48,32 @@ class Energy { for (let i = 0; i < block; i++) { x = x + Helper.rand(3) - 1; y = y + Helper.rand(3) - 1; - if (x < 0 || x >= width || y < 0 || y >= height) {return} - if (world.isFree(x, y)) {world.setDot(x, y, color)} + if (x < 0 || x >= width || y < 0 || y >= height) {return amount} + if (world.isFree(x, y)) { + world.setDot(x, y, color); + if (++amount > maxEnergy) {return amount} + } } + + return amount; } _getEnergyPercent() { - let energy = 0; - const world = this._manager.world; - const width = Config.worldWidth; + let energy = 0; + const world = this._manager.world; + const width = Config.worldWidth; const height = Config.worldHeight; - const poses = this._manager.positions; - const objs = this._manager.objects; + const poses = this._manager.positions; + const objs = this._manager.objects; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { const posId = POSID(x, y); - if (typeof poses[posId] === 'undefined' && typeof objs[posId] === 'undefined') {energy += world.getDot(x, y)} + if (typeof poses[posId] === 'undefined' && typeof objs[posId] === 'undefined' && world.getDot(x, y) > 0) {++energy} } } - return energy / (width * height * 0xffffffff); + return energy / (width * height); } } diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index bbb013c..0ed60b6 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -37,7 +37,7 @@ class Status extends Configurable { super(manager, {Config, cfg: statCfg}, apiCfg); this._status = { - lps :0, ips :0, orgs :0, energy :0, oenergy :0, eenergy:0, wenergy:0, wenergyup:true, changes:0, fit:0, age:0, code:0, + lps :0, ips :0, orgs :0, energy :0, oenergy :0, eenergy:0, wenergy:0, changes :0, fit:0, age:0, code:0, kill:0, killenergy:0, killage:0, killeat:0, killover:0, killout:0, killin :0, killclone:0 }; this._stamp = 0; @@ -56,7 +56,6 @@ class Status extends Configurable { this._times = 0; this._kill = new Array(9); this._worldEnergy = 0.0; - this._worldEnergyUp = true; this._statusCfg = statCfg; this._firstCall = true; @@ -75,7 +74,6 @@ class Status extends Configurable { this._onKillInCb = this._onKillHandlerOrg.bind(this, 7); this._onKillCloneCb = this._onKillHandlerOrg.bind(this, 8); this._onWorldEnergyCb = this._onWorldEnergy.bind(this); - this._onWorldEnergyUpCb = this._onWorldEnergyUp.bind(this); Helper.override(manager, 'onLoop', this._onLoopCb); manager.on(EVENTS.IPS, this._onIpsCb); @@ -92,7 +90,6 @@ class Status extends Configurable { manager.on(EVENTS.KILL_STEP_IN, this._onKillInCb); manager.on(EVENTS.KILL_CLONE, this._onKillCloneCb); manager.on(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); - manager.on(EVENTS.WORLD_ENERGY_UP, this._onWorldEnergyUpCb); _fill(this._kill, 0); } @@ -100,7 +97,6 @@ class Status extends Configurable { destroy() { const man = this.parent; - man.off(EVENTS.WORLD_ENERGY_UP, this._onWorldEnergyUpCb); man.off(EVENTS.WORLD_ENERGY, this._onWorldEnergyCb); man.off(EVENTS.KILL_CLONE, this._onKillCloneCb); man.off(EVENTS.KILL_STEP_IN, this._onKillInCb); @@ -117,7 +113,6 @@ class Status extends Configurable { man.off(EVENTS.IPS, this._onIpsCb); Helper.unoverride(man, 'onLoop', this._onLoopCb); - this._onWorldEnergyUpCb = null; this._onWorldEnergyCb = null; this._onKillOrgCb = null; this._onKillTourCb = null; @@ -199,7 +194,6 @@ class Status extends Configurable { status.killclone = fix(this._kill[8], 2); status.wenergy = fix(this._worldEnergy, 5); - status.wenergyup = this._worldEnergyUp; !this._firstCall && this.onStatus(status, orgs.size); this._onAfterLoop(stamp); @@ -259,10 +253,6 @@ class Status extends Configurable { _onWorldEnergy(percent) { this._worldEnergy = percent; } - - _onWorldEnergyUp(up) { - this._worldEnergyUp = up; - } } module.exports = Status; \ No newline at end of file diff --git a/client/src/manager/plugins/status/charts/Charts.js b/client/src/manager/plugins/status/charts/Charts.js index ccccb0f..3066047 100644 --- a/client/src/manager/plugins/status/charts/Charts.js +++ b/client/src/manager/plugins/status/charts/Charts.js @@ -167,14 +167,13 @@ class Charts extends Status { const enrg = `enrg:${status.eenergy}`; const onrg = `onrg:${status.oenergy}`; const wnrg = `wnrg:${status.wenergy}`; - const wnrgup = status.wenergyup ? '\u2191' : '\u2193'; const code = `cod:${status.code}`; const age = `age:${status.age}`; const kill = `kil:${status.kill}`; const kilo = `kilo:${status.killeat}`; const orgs = `org:${status.orgs}`; - this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${wnrgup} ${enrg} ${onrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; + this._headerEl.textContent = `${man.clientId ? 'id:' + man.clientId : ''} ${conns === '' ? '' : 'con:' + conns} ${ips} ${wnrg} ${enrg} ${onrg} ${code} ${age} ${kill} ${kilo} ${orgs}`; } /** diff --git a/client/src/manager/plugins/status/console/Console.js b/client/src/manager/plugins/status/console/Console.js index 80865fc..07ea2f4 100644 --- a/client/src/manager/plugins/status/console/Console.js +++ b/client/src/manager/plugins/status/console/Console.js @@ -50,14 +50,13 @@ class Console extends Status { const senergy = format(status.energy, 'nrg', 19); const spenergy = format(status.oenergy, 'onrg', 15); const seenergy = format(status.eenergy, 'enrg', 16); - const wenergy = format(status.wenergy + (status.wenergyup ? '\u2191' : '\u2193'), 'wnrg', 14); const skill = format(status.kill, 'kil', 12); const schanges = format(status.changes, 'che', 12); const sage = format(status.age, 'age', 11); const scode = format(status.code, 'cod', 12); // TODO: under Node.js should use Server/Console.xxx() - console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${wenergy}${skill}${schanges}${sage}${scode}`, GREEN, RED); + console.log(`%c${conns}${sips}${slps}${sorgs}%c${senergy}${spenergy}${seenergy}${skill}${schanges}${sage}${scode}`, GREEN, RED); } } diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 97044b1..2ce0a53 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 / 4, + worldWidth: 1920 / 6, /** * {Number} World height */ - worldHeight: 1080 / 4, + worldHeight: 1080 / 6, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 @@ -87,18 +87,18 @@ ClientConfig.init({ * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldEnergyMaxPercent: .0009, + worldEnergyMaxPercent: .5, /** * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldEnergyMinPercent: .0002, + worldEnergyMinPercent: .1, /** * {Number} Percent of stones in a world. Percent from world size: * stoneAmount = worldStonesPercent * worldWidth * worldHeight */ - worldStonesPercent: .1, + worldStonesPercent: .3, /** * {Number} Color index for stones in a world. See Organism.MAX_COLORS * constant for details From 955dc2c933f7477410950f6fd3b90a015ab99b60 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Wed, 28 Mar 2018 23:26:24 +0300 Subject: [PATCH 282/291] new default configs --- client/src/manager/plugins/organisms/Config.js | 12 ++++++------ client/src/share/Config.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 148c4cc..5c2ee3e 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -52,7 +52,11 @@ const Config = { * {Number} Minimum age for cloning. Before that, cloning is impossible. It should * be less then orgAlivePeriod config */ - orgCloneMinAge: 200, + orgCloneMinAge: 700, + /** + * {Number} Minimum energy for cloning + */ + orgCloneMinEnergy: 1000000, /** * {Boolean} If true, then random organism will be killed after new one has * cloned and amount of organisms is greater then orgMaxOrgs config. false @@ -60,10 +64,6 @@ const Config = { * orgMaxOrgs config. */ orgKillOnClone: false, - /** - * {Number} Minimum energy for cloning - */ - orgCloneMinEnergy: 100000, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -100,7 +100,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 500, + orgAlivePeriod: 1000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 2ce0a53..79477c0 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 / 6, + worldWidth: 1920 / 10, /** * {Number} World height */ - worldHeight: 1080 / 6, + worldHeight: 1080 / 10, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 From cd4ce7d4d87c6ad7c9e9f547cd4463301c1e6c9a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 30 Mar 2018 12:38:18 +0300 Subject: [PATCH 283/291] speed optimization test --- client/src/manager/Manager.js | 9 +- client/src/manager/ManagerSpec.js | 40 +++--- .../src/manager/plugins/organisms/Config.js | 2 +- .../src/manager/plugins/organisms/Organism.js | 7 +- .../manager/plugins/organisms/Organisms.js | 130 +++++++----------- .../manager/plugins/organisms/dos/Organism.js | 2 +- .../plugins/organisms/dos/Organisms.js | 4 +- .../plugins/organisms/garmin/Organism.js | 2 +- client/src/manager/plugins/status/Status.js | 13 +- client/src/vm/VM.js | 2 +- common/src/FastArray.js | 114 +++++++++++++++ 11 files changed, 206 insertions(+), 119 deletions(-) create mode 100644 common/src/FastArray.js diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 67acfb0..6e6f634 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -13,7 +13,7 @@ * @author flatline */ const Observer = require('./../../../common/src/Observer'); -const Queue = require('./../../../common/src/Queue'); +const FastArray = require('./../../../common/src/FastArray'); const Config = require('./../share/Config').Config; const OConfig = require('./plugins/organisms/Config'); const Plugins = require('./Plugins'); @@ -38,11 +38,11 @@ class Manager extends Observer { constructor(hasView = true) { super(EVENT_AMOUNT); /** - * {Queue} Queue of organisms in current Manager. Should be used by plugins. - * Organisms plugin walk through this queue and run organism's code all the + * {FastArray} Array of organisms in current Manager. Should be used by plugins. + * Organisms plugin walk through this array and run organism's code all the * time. */ - this.organisms = new Queue(); + this.organisms = new FastArray(OConfig.orgMaxOrgs); /** * {Object} positions of organisms in a world. Is used to prevent collisions * and track all world objects @@ -50,6 +50,7 @@ class Manager extends Observer { this.positions = {}; /** * {Object} Map of world objects like stones, water,... + * TODO: it should be a part of positions object. Remove it! */ this.objects = {}; /** diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 1104b1a..65e367a 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -91,7 +91,7 @@ describe("client/src/manager/Manager", () => { }); it("Checking manager creation and it's properties", (done) => { const man = new Manager(false); - expect(man.organisms.size).toBe(0); + expect(man.organisms.length).toBe(0); expect(Object.keys(man.positions).length).toBe(0); expect(man.codeRuns).toBe(0); expect(!!man.api.version).toBe(true); @@ -288,18 +288,18 @@ describe("client/src/manager/Manager", () => { console.log = () => {}; expect(man1.clientId).toBe(null); expect(man2.clientId).toBe(null); - expect(man1.organisms.size).toBe(0); - expect(man2.organisms.size).toBe(0); + expect(man1.organisms.length).toBe(0); + expect(man2.organisms.length).toBe(0); man1.on(EVENTS.LOOP, () => { if (blocked) {return} - expect(man1.organisms.size).toBe(1); + expect(man1.organisms.length).toBe(1); if (iterated1 && iterated2) {destroy(); return} iterated1 = true; }); man2.on(EVENTS.LOOP, () => { if (blocked) {return} - expect(man2.organisms.size).toBe(1); + expect(man2.organisms.length).toBe(1); if (iterated2 && iterated1) {destroy(); return} iterated2 = true; }); @@ -335,10 +335,10 @@ describe("client/src/manager/Manager", () => { OConfig.orgStartAmount = 1; OConfig.orgRainMutationPeriod = 0; OConfig.orgCloneMutationPercent = 0; - expect(man.organisms.size).toBe(0); + expect(man.organisms.length).toBe(0); man.on(EVENTS.LOOP, () => { if (iterated) {return} - expect(man.organisms.size).toBe(1); + expect(man.organisms.length).toBe(1); man.stop(() => { man.destroy(() => { OConfig.orgCloneMutationPercent = percent; @@ -399,10 +399,10 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - org1 = man1.organisms.first.val; + org1 = man1.organisms.lastAdded(); org1.vm.insertLine(); org1.vm.updateLine(0, 0b00001011000000000000000000000000); // onStepRight() - } else if (man2.organisms.size === 2) { + } else if (man2.organisms.length === 2) { destroy(); } if (iterated1 > 10000) {throw 'Error sending organism between Managers'} @@ -466,7 +466,7 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null && org2 !== null) { - org1 = man1.organisms.first.val; + org1 = man1.organisms.lastAdded(); org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() man1.on(EVENTS.STEP_OUT, () => { expect(doneInc < 3).toBe(true); @@ -474,14 +474,14 @@ describe("client/src/manager/Manager", () => { }); man2.on(EVENTS.STEP_IN, () => { ++doneInc; - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.x).toBe(0); + expect(man1.organisms.length).toBe(1); + expect(man1.organisms.lastAdded().x).toBe(0); }); } else if (org1 !== null && org2 !== null && doneInc === 2) { - expect(man1.organisms.size).toBe(1); - expect(man1.organisms.first.val.x).toBe(0); - expect(man2.organisms.size).toBe(1); - expect(man2.organisms.first.val.x).toBe(0); + expect(man1.organisms.length).toBe(1); + expect(man1.organisms.lastAdded().x).toBe(0); + expect(man2.organisms.length).toBe(1); + expect(man2.organisms.lastAdded().x).toBe(0); destroy(); doneInc++; } @@ -489,7 +489,7 @@ describe("client/src/manager/Manager", () => { iterated1++; }); man2.on(EVENTS.LOOP, () => { - !iterated2 && (org2 = man2.organisms.first.val); + !iterated2 && (org2 = man2.organisms.lastAdded()); iterated2++; }); @@ -554,10 +554,10 @@ describe("client/src/manager/Manager", () => { man1.on(EVENTS.LOOP, () => { if (iterated1 > 0 && iterated2 > 0 && org1 === null) { - expect(man2.organisms.size).toBe(1); - org1 = man1.organisms.first.val; + expect(man2.organisms.length).toBe(1); + org1 = man1.organisms.lastAdded(); org1.vm.code.push(0b00001011000000000000000000000000); // onStepRight() - } else if (man2.organisms.size === 2) { + } else if (man2.organisms.length === 2) { destroy(); } if (iterated1 > 10000) {throw 'Error sending organism between Servers'} diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5c2ee3e..0c75757 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -100,7 +100,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 1000, + orgAlivePeriod: 10000, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 3d86e85..dddcda8 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -70,7 +70,7 @@ class Organism extends Observer { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Object} item Reference to the Queue item, where + * @param {Number} item Reference to the item index, where * this organism is located * @param {Function} operatorCls Class of operators * @param {Organism} parent Parent organism if cloning is needed @@ -88,7 +88,6 @@ class Organism extends Observer { this._iterations = -1; this._changes = 0; this._item = item; - this._maxEnergy = 0; this._energyChanges = 0; this._fnId = 0; } @@ -115,7 +114,6 @@ class Organism extends Observer { set energy(e) {if (this.vm !== null) { this._energy = e; ++this._energyChanges % UPDATE_COLOR_PERIOD === 0 && this._updateColor()}} set startEnergy(e) {this._startEnergy = e} set changes(c) {this._changes = c} - set maxEnergy(e) {this._maxEnergy = e} /** * Runs one code iteration (amount of lines set in Config.codeYieldPeriod) and returns @@ -239,7 +237,8 @@ class Organism extends Observer { } _updateColor() { - this._color = Organism.getColor((this._energy * MAX_COLORS) / this._maxEnergy); + // TODO: implement organism update color logic here + //this._color = Organism.getColor(MAX_COLORS); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 7bb5954..bec0c0c 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -54,20 +54,23 @@ class Organisms extends Configurable { */ createEmptyOrg(...args) {} + /** + * Is called at the end of run() method + * @abstract + */ + onOrganism() {} + constructor(manager) { super(manager, {Config, cfg: OConfig}, { getAmount : ['_apiGetAmount', 'Shows amount of organisms within current Client(Manager)'], - getOrganism: ['_apiGetOrganism', 'Returns organism instance by id or int\'s index in a Queue'] + getOrganism: ['_apiGetOrganism', 'Returns organism instance by id or int\'s index in an array'] }); this.organisms = manager.organisms; this.objects = manager.objects; - this.randOrgItem = this.organisms.first; this.positions = manager.positions; this.world = manager.world; this._mutator = new Mutator(manager, this); - this._maxEnergy = 0; - this._oldMaxEnergy = 0; this._onIterationCb = this._onIteration.bind(this); this._onLoopCb = this._onLoop.bind(this); @@ -77,12 +80,14 @@ class Organisms extends Configurable { } destroy() { - let item = this.organisms.first; - let org; - while (item && (org = item.val)) {org.destroy(); item = item.next} + const orgs = this.organisms; + const len = orgs.length; + for (let i = 0; i < len; i++) {orgs.get(i).destroy()} Helper.unoverride(this.parent, 'onIteration', this._onIterationCb); Helper.unoverride(this.parent, 'onLoop', this._onLoopCb); + this.organisms = null; + this.objects = null; this._mutator.destroy(); this._mutator = null; this._onIterationCb = null; @@ -91,19 +96,6 @@ class Organisms extends Configurable { super.destroy(); } - /** - * Is called at the end of run() method. Updates maxEnergy value for population - * @param {Organism} org Current organism - */ - onOrganism(org) { - if (org.energy > this._oldMaxEnergy) {this._oldMaxEnergy = org.energy} - if (org === this.organisms.last.val) { - this._maxEnergy = this._oldMaxEnergy; - this._oldMaxEnergy = 0; - } - org.maxEnergy = this._maxEnergy; - } - addOrgHandlers(org) { org.on(ORG_EVENTS.DESTROY, this._onDestroyOrg.bind(this)); org.on(ORG_EVENTS.KILL_NO_ENERGY, this._onKillNoEnergyOrg.bind(this)); @@ -135,10 +127,9 @@ class Organisms extends Configurable { createOrg(x, y, parent = null) { if (x === -1) {return false} const orgs = this.organisms; - orgs.add(null); - let org = this.createEmptyOrg(++this._orgId + '', x, y, orgs.last, parent); + let org = this.createEmptyOrg(++this._orgId + '', x, y, orgs.freeIndex, parent); - orgs.last.val = org; + orgs.set(org); this.addOrgHandlers(org); this.world.setDot(x, y, org.color); this.positions[org.posId] = org; @@ -150,19 +141,12 @@ class Organisms extends Configurable { /** * Returns random organism of current population - * @return {Organism|null} + * @return {Organism|false} */ - randOrg() { - const offs = Helper.rand(this.organisms.size) + 1; - let item = this.randOrgItem; - - for (let i = 0; i < offs; i++) { - if ((item = item.next) === null) { - item = this.organisms.first; - } - } - - return (this.randOrgItem = item).val; + _randOrg() { + const org = this.organisms.get(Helper.rand(this.organisms.size)); + if (org === 0) {return false} + return org; } /** @@ -172,13 +156,14 @@ class Organisms extends Configurable { * @param {Number} stamp Time stamp of current iteration */ _onIteration(counter, stamp) { - let item = this.organisms.first; - let org; + const orgs = this.organisms; + const len = orgs.size; + let org; - while (org = item && item.val) { + for (let i = 0; i < len; i++) { + if ((org = orgs.get(i)) === 0) {continue} org.run(); - org.energy > 0 && this.onOrganism(org); - item = item.next; + //this.onOrganism(org); } this._updateTournament(counter); @@ -191,9 +176,12 @@ class Organisms extends Configurable { } _tournament(org1 = null, org2 = null) { - org1 = org1 || this.randOrg(); - org2 = org2 || this.randOrg(); + org1 = org1 || this._randOrg(); + org2 = org2 || this._randOrg(); + if (org1 === false && org2 !== false) {return org2} + if (org2 === false && org1 !== false) {return org1} + if (org1 === false && org2 === false) {return false} if (org1.energy < 1 && org2.energy < 1) {return false} if ((org2.energy > 0 && org1.energy < 1) || this.compare(org2, org1)) { return org2; @@ -208,7 +196,7 @@ class Organisms extends Configurable { let y; [x, y] = this.world.getNearFreePos(org.x, org.y); if (x === -1 || this.createOrg(x, y, org) === false) {return false} - let child = this.organisms.last.val; + let child = this.organisms.lastAdded(); this.onClone(org, child); if (org.energy < 1 || child.energy < 1) {return false} @@ -219,7 +207,7 @@ class Organisms extends Configurable { _crossover(org1, org2) { if (!this._clone(org1, true)) {return false} - let child = this.organisms.last.val; + let child = this.organisms.lastAdded(); if (child.energy > 0 && org2.energy > 0) { child.changes += (Math.abs(child.vm.crossover(org2.vm)) * Num.MAX_BITS); @@ -245,37 +233,20 @@ class Organisms extends Configurable { * @return {Number} Amount of organisms within current Manager */ _apiGetAmount() { - return this.parent.organisms.size; + return this.parent.organisms.length; } /** - * Return organism instance by id or it's index in a Queue + * Return organism instance by id or it's index in an array * @param {Number|String} index Index or id * @return {Organism} Organism instance or null * @api */ _apiGetOrganism(index) { - if (Helper.isNumeric(index)) { - return this.organisms.get(index); - } - - let item = this.organisms.first; - let org; - - while (org = item && item.val) { - if (org.id === index) {return org} - item = item.next; - } - - return null; + return this.organisms.get(index); } _onDestroyOrg(org) { - if (this.randOrgItem === org.item) { - if ((this.randOrgItem = org.item.next) === null) { - this.randOrgItem = this.organisms.first; - } - } this.organisms.del(org.item); this.world.setDot(org.x, org.y, 0); this.positions[org.posId] = undefined; @@ -295,12 +266,12 @@ class Organisms extends Configurable { //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} - //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this.randOrg().destroy()} + //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this._randOrg().destroy()} // if (this.organisms.size >= OConfig.orgMaxOrgs && Math.random() <= ((org.energy / 10000000000000) * (org.iterations / OConfig.orgAlivePeriod))) { - // this.randOrg().destroy(); + // this._randOrg().destroy(); // } //if (this.organisms.size < maxOrgs) {this._clone(org)} - //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this.randOrg().destroy()} + //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this._randOrg().destroy()} // // This is very important part of application! Cloning should be available only if // amount of organisms is less then maximum or if current organism has ate other just @@ -310,14 +281,14 @@ class Organisms extends Configurable { // to clone them. // if (org.energy < OConfig.orgCloneMinEnergy) {return} - if (OConfig.orgKillOnClone && this.organisms.size >= OConfig.orgMaxOrgs) {this.randOrg().destroy()} - if (this.organisms.size < OConfig.orgMaxOrgs) {this._clone(org)} + if (OConfig.orgKillOnClone && this.organisms.length >= OConfig.orgMaxOrgs) {this._randOrg().destroy()} + if (this.organisms.length < OConfig.orgMaxOrgs) {this._clone(org)} } _killInTour() { - let org1 = this.randOrg(); - let org2 = this.randOrg(); - if (org1.energy < 1 || org2.energy < 1 || org1 === org2 || this.organisms.size < 1) {return false} + let org1 = this._randOrg(); + let org2 = this._randOrg(); + if (org1 === false || org2 === false || org1.energy < 1 || org2.energy < 1 || org1 === org2 || this.organisms.length < 1) {return false} const winner = this._tournament(org1, org2); if (winner === false) {return false} @@ -336,12 +307,13 @@ class Organisms extends Configurable { */ _updateTournament(counter) { const period = OConfig.orgTournamentPeriod; - return counter % period === 0 && this.organisms.size > 0 || period !== 0 && this._killInTour(); + return counter % period === 0 && this.organisms.length > 0 || period !== 0 && this._killInTour(); } _updateRandomOrgs(counter) { - if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || this.organisms.size < 1) {return false} - const vm = this.randOrg().vm; + if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || this.organisms.length < 1) {return false} + const vm = this._randOrg().vm; + if (typeof vm === 'undefined') {return false} const size = Helper.rand(vm.size) + 1; const pos = Helper.rand(vm.size - size); @@ -351,14 +323,14 @@ class Organisms extends Configurable { } _updateCrossover(counter) { - const orgAmount = this.organisms.size; + const orgAmount = this.organisms.length; if (counter % OConfig.orgCrossoverPeriod !== 0 || OConfig.orgCrossoverPeriod === 0 || orgAmount < 1) {return false} // // We have to have a possibility to crossover not only with best // organisms, but with low fit also // - let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); + let org1 = Helper.rand(2) === 0 ? this._tournament() : this._randOrg(); + let org2 = Helper.rand(2) === 0 ? this._tournament() : this._randOrg(); if (org1 === false || org2 === false || org1.energy < 1 || org2.energy < 1) {return false} this._crossover(org1, org2); @@ -374,7 +346,7 @@ class Organisms extends Configurable { } _updateCreate() { - if (this.organisms.size < 1) {this._createPopulation()} + if (this.organisms.length < 1) {this._createPopulation()} } } diff --git a/client/src/manager/plugins/organisms/dos/Organism.js b/client/src/manager/plugins/organisms/dos/Organism.js index db11544..9c395a4 100644 --- a/client/src/manager/plugins/organisms/dos/Organism.js +++ b/client/src/manager/plugins/organisms/dos/Organism.js @@ -14,7 +14,7 @@ class OrganismDos extends Organism { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Object} item Reference to the Queue item, where + * @param {Object} item Reference to the item index, where * this organism is located * @param {Organism} parent Parent organism if cloning is needed */ diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index a3b71fb..b2006fc 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -242,8 +242,8 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg(x, y)) { - const org = this.organisms.last.val; + if (ret.ret = this.world.isFree(x, y) && this.organisms.length < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg(x, y)) { + const org = this.organisms.lastAdded(); org.unserialize(orgJson); const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; // diff --git a/client/src/manager/plugins/organisms/garmin/Organism.js b/client/src/manager/plugins/organisms/garmin/Organism.js index 2ed9a63..1f93219 100644 --- a/client/src/manager/plugins/organisms/garmin/Organism.js +++ b/client/src/manager/plugins/organisms/garmin/Organism.js @@ -16,7 +16,7 @@ class OrganismGarmin extends Organism { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Object} item Reference to the Queue item, where + * @param {Object} item Reference to the item index, where * this organism is located * @param {Observer} obs Observer for sending external events * @param {Organism} parent Parent organism if cloning is needed diff --git a/client/src/manager/plugins/status/Status.js b/client/src/manager/plugins/status/Status.js index 0ed60b6..94655b4 100644 --- a/client/src/manager/plugins/status/Status.js +++ b/client/src/manager/plugins/status/Status.js @@ -133,24 +133,25 @@ class Status extends Configurable { } _onBeforeLoop(orgs) { - const size = orgs.size || 1; + const size = orgs.length || 1; let energy = 0; let startEnergy = 0; let iterations = 0; let fitness = 0; let changes = 0; let codeSize = 0; - let item = orgs.first; + const len = orgs.size; let org; - while(item && (org = item.val)) { + for (let i = 0; i < len; i++) { + if ((org = orgs.get(i)) === 0) {continue} + energy += org.energy; startEnergy += org.startEnergy; iterations += org.iterations; changes += org.changes; fitness += org.fitness(); codeSize += org.vm.size; - item = item.next; } this._energy = energy / size; @@ -166,7 +167,7 @@ class Status extends Configurable { if (stamp - this._stamp < this._statusCfg.period) {return} const orgs = this.parent.organisms; const status = this._status; - const orgAmount = orgs.size || 1; + const orgAmount = orgs.length || 1; const fix = Status._toFixed; this._onBeforeLoop(orgs); @@ -195,7 +196,7 @@ class Status extends Configurable { status.wenergy = fix(this._worldEnergy, 5); - !this._firstCall && this.onStatus(status, orgs.size); + !this._firstCall && this.onStatus(status, orgs.length); this._onAfterLoop(stamp); this._firstCall = false; } diff --git a/client/src/vm/VM.js b/client/src/vm/VM.js index df075bd..912075d 100644 --- a/client/src/vm/VM.js +++ b/client/src/vm/VM.js @@ -38,7 +38,7 @@ class VM extends Observer { */ this._operatorCls = operatorCls; this._vars = parent && parent.vars && parent.vars.slice() || this._getVars(); - this._code = parent && parent.code.slice() || []; + this._code = parent && parent.code.slice() || [102010341,226191885,200109152,129239321,120230511,212700737,146086204,169006534,70810654,236109088,21009195,234433901,101041014,153424224,172525892,163739837,155055718,77473223,160792938,204092844,4306977,186406410,128227592,43980086,130041897,170032548,169377297,43538070,192001244,179556805,174174625,228493827,100127000,117130125,117350792,64579162,230088461,180523805,22716019,44503895,111912075,106541750,185900561,49424461,314484569,248020267,284600795,196179104,81616173,220252955,66643426,138471815,249522957,225747005,235973814,78136757,245329089,149223185,196325976,90216701,8462368,243745810,275565066,315780670,126426118,115017256,77957900,43382097,219086631,104748276,164034927,187161306,258273627,274605007,251246552,109875154,162762758,359649722,21631269,160939590,135635862,347922125,47028039,103268861,33481886,328856887,320791974,102564578,325584338,240155556,310956581,332262718,281115585,255416298,56526016,216202570,58797126,275216084,179188444,35510775,107078419,162372242,159561416,104749340,49147506,293127740,25086557,14592669,218266840,206369309,356664114,282757190,32154896,250704101,162011880,27817768,73719754,321995331,227372609,173701786,140441376,65150789,243661913,279503892,361150067,197003070,265075520,335490183,359239278,208746301,251849157,322961773,250102086,177132823,10844881,221170368,42612495,164266783,213415703,50989721,253159322,75201397,75251243,284287480,239248288,343706359,234422168,73881170,32873066,140694443,230224009,329578189,302029688,260641276,221145114,271848517,112587146,27508187,160255454,217141050,289882814,110551028,362065745,266639784,189905639,328721510,22595828,92652025,16331860,84397251,110717070,167809194,282893655,149087879,341641799,305877171,47949897,30226804,29326378,5264065,3678030,30424703,274541192,15582110,315125937,10197952,64891919,13488022,177812387,162546279,200029263,142513059,119173917,197197175,245368115,147431662,247202501,356282075,67619626,177488883,185579907,60773224,43475771,250230335,183756732,102482623,58855704,258031147,29380608,332941197,267519551,158300456,20657085,163286523,226819902,308407044,328653284,317906531,276205476,256029358,79858422,89507380,145382882,171365579,246648979,32492304,159618173,3495690,124775704,358284547,263102533,88173398,223264957,200192193,21895446,23743162,192632381,6808375,66977796,93933517,269180908,260451782,303919301,296916921,62045740,247446069,62373497,108595985,341153042,298156406,20044425,104442678,78640255,355434367,120774734,148331569,287988242,8160318,89074002,172314486,213954846,342087621,262752812,308777822,67506084,280464307,285708168,15893307,222003070,194495371,262797388,304341003,253569188,278781631,218966877,5287177,74769522,183066598,352253018,34275085,52652201,207034345,177281005,47776967,296444150,260109248,270954962,175777346,167008262,211047529,246835341,172653707,275430467,96022556,82811972,277058972,6631344,66068938,223872328,5351498]; this._line = parent && parent.line || 0; /** * {Array} Array of two numbers. first - line number where we have diff --git a/common/src/FastArray.js b/common/src/FastArray.js new file mode 100644 index 0000000..24b5122 --- /dev/null +++ b/common/src/FastArray.js @@ -0,0 +1,114 @@ +/** + * Implementation of fast array. First assumption of this class is in fixed array + * size. Second that get() method will be called must more times, then set() or + * del() or resize(). Resize is possible, but should be rare to keep it fast. Is + * used for storing organisms population. This class doesn't check size overflow + * due performance issue. Removing element means setting 0 to specified index. + * This class should not be used for storing numbers! + * + * @author flatline + */ +class FastArray { + constructor(size) { + /** + * {Array} Source container for custom objects + */ + this._arr = new Array(size); + /** + * {Array} Array of free indexes in _arr. Every time + * user calls del() method _arr obtains hole in it. + * Index of this hole wil be stored in this array + */ + this._freeIndexes = new Array(size); + /** + * {Number} Index of last free index in _freeIndexes array + */ + this._index = size - 1; + /** + * {Number} Allocated size of array. This is maximum amount + * of elements, which may be stored in FastArray + */ + this._size = size; + + for (let i = 0; i < size; i++) { + this._freeIndexes[i] = i; + this._arr[i] = 0; + } + } + + destroy() { + this._arr = null; + this._freeIndexes = null; + this._size = 0; + } + + /** + * Analog of Array.length + * @returns {Number} Amount of not empty elements in FastArray. + * Not all cells in an array may be filled by values. + */ + get length() {return this._size - this._index - 1} + + /** + * Returns allocated size + * @returns {Number} + */ + get size() {return this._size} + + /** + * Returns next free index in FastArray + * @returns {Number} + */ + get freeIndex() { + return this._freeIndexes[this._index]; + } + + /** + * Sets value to FastArray. You can't set value index due to + * optimization reason. Only a value + * @param {*} v Any value except number + */ + set(v) {this._arr[this._freeIndexes[this._index--]] = v} + + /** + * Returns a value by index + * @param {Number} i Value index + * @returns {*} + */ + get(i) {return this._arr[i]} + + /** + * Removes a value by index + * @param {Number} i Value index + */ + del(i) { + if (this._arr !== 0) + this._arr[i] = 0; + this._freeIndexes[++this._index] = i; + } + + /** + * Returns last added value by set() method + * @returns {*} Value + */ + lastAdded() { + return this._arr[this._freeIndexes[this._index + 1]]; + } + + /** + * Resizes an array. Values will not be removed during resize. + * This method is very slow and should be called not often. + * @param {Number} size New array size + */ + resize(size) { + const indexes = this._freeIndexes; + const arr = this._arr; + this._index = -1; + arr.length = indexes.length = (this._size = size); + for (let i = 0; i < size; i++) { + (arr[i] === 0) && (indexes[++this._index] = i); + } + } +} + +module.exports = FastArray; \ No newline at end of file From 1072b65da621c81b72f912bf238279755280322b Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 30 Mar 2018 17:48:59 +0300 Subject: [PATCH 284/291] speed optimization organisms colors changed to red all the time --- .../src/manager/plugins/organisms/Organism.js | 4 +- .../plugins/organisms/dos/Operators.js | 64 ++++++++++++++----- .../plugins/organisms/dos/Organisms.js | 4 -- client/src/share/Config.js | 4 +- 4 files changed, 53 insertions(+), 23 deletions(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 3d86e85..535e123 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -193,6 +193,7 @@ class Organism extends Observer { fitness() { // TODO: check these variants //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); + //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy) * (this._changes || 1); //return (OConfig.codeMaxSize + 1 - this.vm.size) * (this._energy - this._startEnergy); //return (OConfig.codeMaxSize + 1 - this.vm.size) * ((this._energy - this._startEnergy) / this._iterations); return this._energy / (this.vm.size || 1); @@ -239,7 +240,8 @@ class Organism extends Observer { } _updateColor() { - this._color = Organism.getColor((this._energy * MAX_COLORS) / this._maxEnergy); + // TODO: color update strategy will be here... + //this._color = Organism.getColor(MAX_COLORS)); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 527188b..2dab080 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -217,10 +217,54 @@ class OperatorsDos extends Operators { return ++line; } - onEatLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x - 1, org.y); return ++line} - onEatRight(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x + 1, org.y); return ++line} - onEatUp(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y - 1); return ++line} - onEatDown(num, line, org) {this.vars[Num.getVar0(num)] = this._eat(org, num, org.x, org.y + 1); return ++line} + onEatLeft(num, line, org) { + const amount = this.vars[Num.getVar1(num)]; + if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} + const ret = this._ret; + + ret.ret = amount; + this.obs.fire(EVENTS.EAT, org, org.x - 1, org.y, ret); + org.energy += ret.ret; + this.vars[Num.getVar0(num)] = ret.ret; + + return ++line; + } + onEatRight(num, line, org) { + const amount = this.vars[Num.getVar1(num)]; + if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} + const ret = this._ret; + + ret.ret = amount; + this.obs.fire(EVENTS.EAT, org, org.x + 1, org.y, ret); + org.energy += ret.ret; + this.vars[Num.getVar0(num)] = ret.ret; + + return ++line; + } + onEatUp(num, line, org) { + const amount = this.vars[Num.getVar1(num)]; + if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} + const ret = this._ret; + + ret.ret = amount; + this.obs.fire(EVENTS.EAT, org, org.x, org.y - 1, ret); + org.energy += ret.ret; + this.vars[Num.getVar0(num)] = ret.ret; + + return ++line; + } + onEatDown(num, line, org) { + const amount = this.vars[Num.getVar1(num)]; + if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} + const ret = this._ret; + + ret.ret = amount; + this.obs.fire(EVENTS.EAT, org, org.x, org.y + 1, ret); + org.energy += ret.ret; + this.vars[Num.getVar0(num)] = ret.ret; + + return ++line; + } onStepLeft(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x - 1, org.y, org.x - 1); return ++line} onStepRight(num, line, org) {this.vars[Num.getVar0(num)] = this._step(org, org.x, org.y, org.x + 1, org.y, org.x + 1); return ++line} @@ -272,18 +316,6 @@ class OperatorsDos extends Operators { return ++line; } - _eat(org, num, x, y) { - const amount = this.vars[Num.getVar1(num)]; - if (amount === 0) {return 0} - const ret = this._ret; - - ret.ret = amount; - this.obs.fire(EVENTS.EAT, org, x, y, ret); - org.energy += ret.ret; - - return ret.ret; - } - _step(org, x1, y1, x2, y2, step) { this.obs.fire(EVENTS.STEP, org, x1, y1, x2, y2); return org.x === x2 && org.y === y2 ? step : 0; diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index a3b71fb..e604ddb 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -128,10 +128,6 @@ class Organisms extends BaseOrganisms { } _onEat(org, x, y, ret) { - // - // Amount of eat energy depends on organism size. Small organisms - // eat less, big - more - // const eat = ret.ret; [x, y] = NORMALIZE_NO_DIR(x, y); const posId = POSID(x, y); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 79477c0..f37200f 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -53,11 +53,11 @@ ClientConfig.init({ /** * {Number} World width */ - worldWidth: 1920 / 10, + worldWidth: 1920, /** * {Number} World height */ - worldHeight: 1080 / 10, + worldHeight: 1080, /** * {Number} Turns on cyclic world mode. It means that organisms may go outside * it's border, but still be inside. For example, if the world has 10x10 From bd55bd8af4a7e29f01ac3339fad91b224fe4ead0 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 30 Mar 2018 19:33:31 +0300 Subject: [PATCH 285/291] removed objects map optimized positions map --- client/src/manager/Manager.js | 10 +++--- client/src/manager/ManagerSpec.js | 2 +- client/src/manager/plugins/Energy.js | 14 +++----- client/src/manager/plugins/Stones.js | 5 ++- .../manager/plugins/organisms/Organisms.js | 11 +++---- .../plugins/organisms/dos/Organisms.js | 32 ++++++------------- 6 files changed, 26 insertions(+), 48 deletions(-) diff --git a/client/src/manager/Manager.js b/client/src/manager/Manager.js index 67acfb0..190f614 100644 --- a/client/src/manager/Manager.js +++ b/client/src/manager/Manager.js @@ -37,6 +37,8 @@ class Manager extends Observer { */ constructor(hasView = true) { super(EVENT_AMOUNT); + const width = Config.worldWidth; + const height = Config.worldHeight; /** * {Queue} Queue of organisms in current Manager. Should be used by plugins. * Organisms plugin walk through this queue and run organism's code all the @@ -47,11 +49,8 @@ class Manager extends Observer { * {Object} positions of organisms in a world. Is used to prevent collisions * and track all world objects */ - this.positions = {}; - /** - * {Object} Map of world objects like stones, water,... - */ - this.objects = {}; + this.positions = []; + for (let x = 0; x < width; x++) {this.positions[x] = (new Array(height)).fill(0)} /** * {Object} This field is used as a container for public API of the Manager. * It may be used in a user console by the Operator of construct. Plugins @@ -197,7 +196,6 @@ class Manager extends Observer { this._world = null; this.api = null; this._codeRuns = 0; - this.objects = null; this.positions = null; this.organisms.destroy(); this.organisms = null; diff --git a/client/src/manager/ManagerSpec.js b/client/src/manager/ManagerSpec.js index 1104b1a..254c847 100644 --- a/client/src/manager/ManagerSpec.js +++ b/client/src/manager/ManagerSpec.js @@ -92,7 +92,7 @@ describe("client/src/manager/Manager", () => { it("Checking manager creation and it's properties", (done) => { const man = new Manager(false); expect(man.organisms.size).toBe(0); - expect(Object.keys(man.positions).length).toBe(0); + expect(man.positions.length).toBe(Config.worldWidth); expect(man.codeRuns).toBe(0); expect(!!man.api.version).toBe(true); expect(man.api.visualize).toBe(undefined); diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 935af0b..ca492f4 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -8,8 +8,6 @@ const Config = require('./../../share/Config').Config; const Organism = require('./../../manager/plugins/organisms/Organism').Organism; const EVENTS = require('./../../share/Events').EVENTS; -const POSID = Helper.posId; - class Energy { constructor(manager) { this._manager = manager; @@ -59,17 +57,15 @@ class Energy { } _getEnergyPercent() { - let energy = 0; - const world = this._manager.world; - const width = Config.worldWidth; + let energy = 0; + const world = this._manager.world; + const width = Config.worldWidth; const height = Config.worldHeight; - const poses = this._manager.positions; - const objs = this._manager.objects; + const poses = this._manager.positions; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - const posId = POSID(x, y); - if (typeof poses[posId] === 'undefined' && typeof objs[posId] === 'undefined' && world.getDot(x, y) > 0) {++energy} + if (poses[x][y] === 0 && world.getDot(x, y) > 0) {++energy} } } diff --git a/client/src/manager/plugins/Stones.js b/client/src/manager/plugins/Stones.js index 7697fe4..ae155c8 100644 --- a/client/src/manager/plugins/Stones.js +++ b/client/src/manager/plugins/Stones.js @@ -9,11 +9,10 @@ const Organism = require('./../../manager/plugins/organisms/Organism').Organ const OBJECT_TYPES = require('./../../view/World').OBJECT_TYPES; const STONE_BLOCK_SIZE = 300; -const POSID = Helper.posId; // // We have to add stone type to global types storage // -OBJECT_TYPES.TYPE_STONE = Object.keys(OBJECT_TYPES).length; +OBJECT_TYPES.TYPE_STONE = -(Object.keys(OBJECT_TYPES).length + 1); class Stones { constructor(manager) { @@ -55,7 +54,7 @@ class Stones { if (x < 0 || x >= width || y < 0 || y >= height) {return amount} if (world.isFree(x, y)) { if (world.setDot(x, y, color)) { - man.objects[POSID(x, y)] = stone; + man.positions[x][y] = stone; if (++amount >= stones) {return amount} } } diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 7bb5954..7473a46 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -17,8 +17,6 @@ const ORG_EVENTS = require('./../../../../src/manager/plugins/organisms/Organi const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); -const POSID = Helper.posId; - // TODO: inherit this class from Configurable class Organisms extends Configurable { /** @@ -60,7 +58,6 @@ class Organisms extends Configurable { getOrganism: ['_apiGetOrganism', 'Returns organism instance by id or int\'s index in a Queue'] }); this.organisms = manager.organisms; - this.objects = manager.objects; this.randOrgItem = this.organisms.first; this.positions = manager.positions; this.world = manager.world; @@ -126,8 +123,8 @@ class Organisms extends Configurable { if (x1 === x2 && y1 === y2) {return false} world.setDot(x1, y1, 0); - this.positions[POSID(x1, y1)] = undefined; - this.positions[POSID(x2, y2)] = org; + this.positions[x1][y1] = 0; + this.positions[x2][y2] = org; return true; } @@ -141,7 +138,7 @@ class Organisms extends Configurable { orgs.last.val = org; this.addOrgHandlers(org); this.world.setDot(x, y, org.color); - this.positions[org.posId] = org; + this.positions[x][y] = org; this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); @@ -278,7 +275,7 @@ class Organisms extends Configurable { } this.organisms.del(org.item); this.world.setDot(org.x, org.y, 0); - this.positions[org.posId] = undefined; + this.positions[org.x][org.y] = 0; this.parent.fire(EVENTS.KILL, org); //Console.info(org.id, ' die'); } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index e604ddb..11273d9 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -30,11 +30,6 @@ const OBJECT = 3; */ const NORMALIZE = Helper.normalize; const NORMALIZE_NO_DIR = Helper.normalizeNoDir; -/** - * {Function} Is created to speed up this function call. constants are run - * much faster, then Helper.posId() - */ -const POSID = Helper.posId; class Organisms extends BaseOrganisms { constructor(manager) { @@ -118,31 +113,25 @@ class Organisms extends BaseOrganisms { } _onGetEnergy(x, y, ret) { - const posId = POSID(x, y); - - if (typeof(this.positions[posId]) === 'undefined') { + if (this.positions[x][y] <= 0) { ret.ret = this.world.getDot(x, y) } else { - ret.ret = this.positions[posId].energy; + ret.ret = this.positions[x][y].energy; } } _onEat(org, x, y, ret) { const eat = ret.ret; [x, y] = NORMALIZE_NO_DIR(x, y); - const posId = POSID(x, y); + const victimOrg = this.positions[x][y]; // // World object found. We can't eat objects // - if (typeof(this.objects[posId]) !== 'undefined') { - ret.ret = 0; - return; - } + if (victimOrg < 0) {ret.ret = 0; return} // // Energy found // - const victimOrg = this.positions[posId]; - if (typeof victimOrg === 'undefined') { + if (victimOrg === 0) { if (eat >= 0) { ret.ret = this.world.grabDot(x, y, eat); this.parent.fire(EVENTS.EAT_ENERGY, ret.ret); @@ -215,14 +204,13 @@ class Organisms extends BaseOrganisms { } _onCheckAt(x, y, ret) { - const posId = POSID(x, y); - [x, y] = NORMALIZE_NO_DIR(x, y); + [x, y] = NORMALIZE_NO_DIR(x, y); - if (typeof(this.objects[posId]) !== 'undefined') { - ret.ret = OBJECT + this.objects[posId]; - } else if (typeof(this.positions[posId]) === 'undefined') { + if (this.positions[x][y] < 0) { // world object + ret.ret = OBJECT + -this.positions[x][y]; + } else if (this.positions[x][y] === 0) { // energy ret.ret = this.world.getDot(x, y) > 0 ? ENERGY : EMPTY; - } else { + } else { // organism ret.ret = ORGANISM; } } From 20993d7db99ca73887aca5d7a7bf45520e622c64 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 30 Mar 2018 20:24:31 +0300 Subject: [PATCH 286/291] comments mistakes were fixed --- client/src/manager/plugins/organisms/Organism.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index d7dd838..64ae058 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -70,7 +70,7 @@ class Organism extends Observer { * @param {String} id Unique identifier of organism * @param {Number} x Unique X coordinate * @param {Number} y Unique Y coordinate - * @param {Number} item Reference to the item index, where + * @param {Object} item Reference to the Queue item, where * this organism is located * @param {Function} operatorCls Class of operators * @param {Organism} parent Parent organism if cloning is needed From c5800f2115b16dd5c053f0fa7eb15187ab2eb740 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Fri, 30 Mar 2018 23:09:53 +0300 Subject: [PATCH 287/291] Fixed #131 --- client/src/manager/plugins/Energy.js | 17 +++++++------- client/src/manager/plugins/Stones.js | 23 +++++++++---------- .../src/manager/plugins/organisms/Config.js | 4 ++-- .../plugins/organisms/dos/Operators.js | 8 +++---- client/src/share/Config.js | 4 ++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index ca492f4..79ff0ae 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -35,13 +35,14 @@ class Energy { } _addEnergyBlock(amount, maxEnergy) { - const width = Config.worldWidth; - const height = Config.worldHeight; - const color = Organism.getColor(Config.worldEnergyColorIndex); - let block = Config.worldEnergyBlockSize; - const world = this._manager.world; - let x = Helper.rand(width); - let y = Helper.rand(height); + const startAmount = amount; + const width = Config.worldWidth; + const height = Config.worldHeight; + const color = Organism.getColor(Config.worldEnergyColorIndex); + let block = Config.worldEnergyBlockSize; + const world = this._manager.world; + let x = Helper.rand(width); + let y = Helper.rand(height); for (let i = 0; i < block; i++) { x = x + Helper.rand(3) - 1; @@ -53,7 +54,7 @@ class Energy { } } - return amount; + return amount > startAmount ? amount : Infinity; } _getEnergyPercent() { diff --git a/client/src/manager/plugins/Stones.js b/client/src/manager/plugins/Stones.js index ae155c8..204d79d 100644 --- a/client/src/manager/plugins/Stones.js +++ b/client/src/manager/plugins/Stones.js @@ -33,20 +33,19 @@ class Stones { const stones = Config.worldStonesPercent * Config.worldWidth * Config.worldHeight; let amount = 0; - while (amount < stones) { - amount = this._addStoneBlock(amount, stones); - } + while ((amount = this._addStoneBlock(amount, stones)) < stones) {} } _addStoneBlock(amount, stones) { - const width = Config.worldWidth; - const height = Config.worldHeight; - const color = Organism.getColor(Config.worldStoneColorIndex); - const man = this._manager; - const world = man.world; - const stone = OBJECT_TYPES.TYPE_STONE; - let x = Helper.rand(width); - let y = Helper.rand(height); + const startAmount = amount; + const width = Config.worldWidth; + const height = Config.worldHeight; + const color = Organism.getColor(Config.worldStoneColorIndex); + const man = this._manager; + const world = man.world; + const stone = OBJECT_TYPES.TYPE_STONE; + let x = Helper.rand(width); + let y = Helper.rand(height); for (let i = 0; i < STONE_BLOCK_SIZE; i++) { x = x + Helper.rand(3) - 1; @@ -60,7 +59,7 @@ class Stones { } } - return amount; + return amount > startAmount ? amount : Infinity; } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 5c2ee3e..48a70b1 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -126,11 +126,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 1000, + orgMaxOrgs: 100, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 1000, + orgStartAmount: 100, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/manager/plugins/organisms/dos/Operators.js b/client/src/manager/plugins/organisms/dos/Operators.js index 2dab080..e99548c 100644 --- a/client/src/manager/plugins/organisms/dos/Operators.js +++ b/client/src/manager/plugins/organisms/dos/Operators.js @@ -217,7 +217,7 @@ class OperatorsDos extends Operators { return ++line; } - onEatLeft(num, line, org) { + onEatLeft(num, line, org) { const amount = this.vars[Num.getVar1(num)]; if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} const ret = this._ret; @@ -229,7 +229,7 @@ class OperatorsDos extends Operators { return ++line; } - onEatRight(num, line, org) { + onEatRight(num, line, org) { const amount = this.vars[Num.getVar1(num)]; if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} const ret = this._ret; @@ -241,7 +241,7 @@ class OperatorsDos extends Operators { return ++line; } - onEatUp(num, line, org) { + onEatUp(num, line, org) { const amount = this.vars[Num.getVar1(num)]; if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} const ret = this._ret; @@ -253,7 +253,7 @@ class OperatorsDos extends Operators { return ++line; } - onEatDown(num, line, org) { + onEatDown(num, line, org) { const amount = this.vars[Num.getVar1(num)]; if (amount === 0) {this.vars[Num.getVar0(num)] = 0; return ++line} const ret = this._ret; diff --git a/client/src/share/Config.js b/client/src/share/Config.js index f37200f..98d4399 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -87,7 +87,7 @@ ClientConfig.init({ * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldEnergyMaxPercent: .5, + worldEnergyMaxPercent: .9, /** * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the @@ -98,7 +98,7 @@ ClientConfig.init({ * {Number} Percent of stones in a world. Percent from world size: * stoneAmount = worldStonesPercent * worldWidth * worldHeight */ - worldStonesPercent: .3, + worldStonesPercent: .25, /** * {Number} Color index for stones in a world. See Organism.MAX_COLORS * constant for details From c5d479f55e3b258b8b4267233f1170f83d611608 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 31 Mar 2018 00:37:02 +0300 Subject: [PATCH 288/291] Fixed an issue with incorrect energy percent calculation Changed default configuration n --- client/src/manager/plugins/Energy.js | 3 +-- client/src/manager/plugins/organisms/Config.js | 6 +++--- client/src/share/Config.js | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 79ff0ae..1f68022 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -62,11 +62,10 @@ class Energy { const world = this._manager.world; const width = Config.worldWidth; const height = Config.worldHeight; - const poses = this._manager.positions; for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - if (poses[x][y] === 0 && world.getDot(x, y) > 0) {++energy} + if (world.getDot(x, y) > 0) {++energy} } } diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index 48a70b1..ffe2f38 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -56,7 +56,7 @@ const Config = { /** * {Number} Minimum energy for cloning */ - orgCloneMinEnergy: 1000000, + orgCloneMinEnergy: 100000, /** * {Boolean} If true, then random organism will be killed after new one has * cloned and amount of organisms is greater then orgMaxOrgs config. false @@ -126,11 +126,11 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 100, + orgMaxOrgs: 200, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 100, + orgStartAmount: 200, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 98d4399..1468b5e 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -93,7 +93,7 @@ ClientConfig.init({ * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldEnergyMinPercent: .1, + worldEnergyMinPercent: .3, /** * {Number} Percent of stones in a world. Percent from world size: * stoneAmount = worldStonesPercent * worldWidth * worldHeight From ca687c93539cefe1e146b4f3645b99e983cf9e74 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sat, 31 Mar 2018 12:07:20 +0300 Subject: [PATCH 289/291] fixed one broken test fixed an issue with wrong energy calculation --- client/src/manager/plugins/Energy.js | 39 ++++++++++++------- client/src/manager/plugins/Stones.js | 18 ++++++--- .../plugins/organisms/dos/OrganismSpec.js | 2 +- client/src/share/Config.js | 2 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/client/src/manager/plugins/Energy.js b/client/src/manager/plugins/Energy.js index 1f68022..938057a 100644 --- a/client/src/manager/plugins/Energy.js +++ b/client/src/manager/plugins/Energy.js @@ -29,32 +29,45 @@ class Energy { this._manager.fire(EVENTS.WORLD_ENERGY, energy); if (energy > Config.worldEnergyMinPercent) {return} + const maxEnergy = Config.worldEnergyMaxPercent * Config.worldWidth * Config.worldHeight; - let amount = 0; - while ((amount = this._addEnergyBlock(amount, maxEnergy)) < maxEnergy) {} + let amount = 0; + let attempts = 0; + while (amount < maxEnergy && attempts < 100) { + const startAmount = amount; + amount = this._addEnergyBlock(amount, maxEnergy); + if (amount === startAmount) { + attempts++; + } else { + attempts = 0; + } + } } _addEnergyBlock(amount, maxEnergy) { - const startAmount = amount; - const width = Config.worldWidth; - const height = Config.worldHeight; - const color = Organism.getColor(Config.worldEnergyColorIndex); - let block = Config.worldEnergyBlockSize; - const world = this._manager.world; - let x = Helper.rand(width); - let y = Helper.rand(height); + const width = Config.worldWidth; + const height = Config.worldHeight; + const color = Organism.getColor(Config.worldEnergyColorIndex); + let block = Config.worldEnergyBlockSize; + const world = this._manager.world; + let x = Helper.rand(width); + let y = Helper.rand(height); for (let i = 0; i < block; i++) { x = x + Helper.rand(3) - 1; y = y + Helper.rand(3) - 1; - if (x < 0 || x >= width || y < 0 || y >= height) {return amount} + if (x < 0 || x >= width || y < 0 || y >= height) { + return amount + } if (world.isFree(x, y)) { world.setDot(x, y, color); - if (++amount > maxEnergy) {return amount} + if (++amount > maxEnergy) { + return amount + } } } - return amount > startAmount ? amount : Infinity; + return amount; } _getEnergyPercent() { diff --git a/client/src/manager/plugins/Stones.js b/client/src/manager/plugins/Stones.js index 204d79d..344b717 100644 --- a/client/src/manager/plugins/Stones.js +++ b/client/src/manager/plugins/Stones.js @@ -31,13 +31,21 @@ class Stones { _onLoop(counter) { if (counter > 1 || Config.worldStonesPercent === .0) {return} - const stones = Config.worldStonesPercent * Config.worldWidth * Config.worldHeight; - let amount = 0; - while ((amount = this._addStoneBlock(amount, stones)) < stones) {} + const stones = Config.worldStonesPercent * Config.worldWidth * Config.worldHeight; + let amount = 0; + let attempts = 0; + while (amount < stones && attempts < 100) { + const startAmount = amount; + amount = this._addStoneBlock(amount, stones); + if (startAmount === amount) { + attempts++; + } else { + attempts = 0; + } + } } _addStoneBlock(amount, stones) { - const startAmount = amount; const width = Config.worldWidth; const height = Config.worldHeight; const color = Organism.getColor(Config.worldStoneColorIndex); @@ -59,7 +67,7 @@ class Stones { } } - return amount > startAmount ? amount : Infinity; + return amount; } } diff --git a/client/src/manager/plugins/organisms/dos/OrganismSpec.js b/client/src/manager/plugins/organisms/dos/OrganismSpec.js index c116ac0..460d1b0 100644 --- a/client/src/manager/plugins/organisms/dos/OrganismSpec.js +++ b/client/src/manager/plugins/organisms/dos/OrganismSpec.js @@ -160,7 +160,7 @@ describe("client/src/organism/OrganismDos", () => { const color = org.color; expect(org.color).toBe(color); org.energy++; - expect(org.color).not.toBe(color); + expect(org.color).toBe(color); }); }); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 1468b5e..0767836 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -87,7 +87,7 @@ ClientConfig.init({ * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldEnergyMaxPercent: .9, + worldEnergyMaxPercent: .7, /** * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the From ba9bfd117089a4eef525da349d1c3bc0a913dcb9 Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Sun, 1 Apr 2018 01:49:05 +0300 Subject: [PATCH 290/291] from now organism color shows his age (green - young, red - old) fixed very critical issue with burning of child t the end of life --- .../src/manager/plugins/organisms/Config.js | 10 ++++---- .../src/manager/plugins/organisms/Organism.js | 5 +--- .../manager/plugins/organisms/Organisms.js | 22 +++++++++--------- .../plugins/organisms/dos/Organisms.js | 6 +++-- client/src/share/Config.js | 2 +- common/src/Queue.js | 23 +++++++++++++++++++ 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index ffe2f38..ed7ac4d 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -52,11 +52,11 @@ const Config = { * {Number} Minimum age for cloning. Before that, cloning is impossible. It should * be less then orgAlivePeriod config */ - orgCloneMinAge: 700, + orgCloneMinAge: 300, /** * {Number} Minimum energy for cloning */ - orgCloneMinEnergy: 100000, + orgCloneMinEnergy: 2000000, /** * {Boolean} If true, then random organism will be killed after new one has * cloned and amount of organisms is greater then orgMaxOrgs config. false @@ -126,17 +126,17 @@ const Config = { * try to clone itself, when entire amount of organisms are equal * this value, the cloning will not happen. */ - orgMaxOrgs: 200, + orgMaxOrgs: 1000, /** * {Number} Amount of organisms we have to create on program start */ - orgStartAmount: 200, + orgStartAmount: 1000, /** * {Number} Amount of energy for first organisms. They are like Adam and * Eve. It means that these empty (without vm) organism were created * by operator and not by evolution. */ - orgStartEnergy: 1000000, + orgStartEnergy: 90000000, /** * {Number} Amount of bits for storing a numeric constant inside byte code */ diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index 64ae058..c8c7224 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -47,8 +47,6 @@ class Organism extends Observer { return r << 16 | g << 8 | b; } - static getMaxColors() {return MAX_COLORS} - /** * Is called before every run. Should return true, if everything * is okay and we don't need to interrupt running. If true, then @@ -238,8 +236,7 @@ class Organism extends Observer { } _updateColor() { - // TODO: color update strategy will be here... - //this._color = Organism.getColor(MAX_COLORS)); + this._color = Organism.getColor(this._iterations * (MAX_COLORS / OConfig.orgAlivePeriod)); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 7473a46..771fda9 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -131,18 +131,17 @@ class Organisms extends Configurable { createOrg(x, y, parent = null) { if (x === -1) {return false} - const orgs = this.organisms; - orgs.add(null); - let org = this.createEmptyOrg(++this._orgId + '', x, y, orgs.last, parent); + const item = this.organisms.addAfter(this.randOrgItem, null); + let org = this.createEmptyOrg(++this._orgId + '', x, y, item, parent); - orgs.last.val = org; + item.val = org; this.addOrgHandlers(org); this.world.setDot(x, y, org.color); this.positions[x][y] = org; this.parent.fire(EVENTS.BORN_ORGANISM, org); //Console.info(org.id, ' born'); - return true; + return item; } /** @@ -203,20 +202,22 @@ class Organisms extends Configurable { if (this.onBeforeClone(org) === false) {return false} let x; let y; + let item; [x, y] = this.world.getNearFreePos(org.x, org.y); - if (x === -1 || this.createOrg(x, y, org) === false) {return false} - let child = this.organisms.last.val; + if (x === -1 || (item = this.createOrg(x, y, org)) === false) {return false} + let child = item.val; this.onClone(org, child); if (org.energy < 1 || child.energy < 1) {return false} this.parent.fire(EVENTS.CLONE, org, child, isCrossover); - return true; + return item; } _crossover(org1, org2) { - if (!this._clone(org1, true)) {return false} - let child = this.organisms.last.val; + const item = this._clone(org1, true); + if (item === false) {return false} + let child = item.val; if (child.energy > 0 && org2.energy > 0) { child.changes += (Math.abs(child.vm.crossover(org2.vm)) * Num.MAX_BITS); @@ -306,7 +307,6 @@ class Organisms extends Configurable { // organisms before cloning. They should kill each other to have a possibility // to clone them. // - if (org.energy < OConfig.orgCloneMinEnergy) {return} if (OConfig.orgKillOnClone && this.organisms.size >= OConfig.orgMaxOrgs) {this.randOrg().destroy()} if (this.organisms.size < OConfig.orgMaxOrgs) {this._clone(org)} } diff --git a/client/src/manager/plugins/organisms/dos/Organisms.js b/client/src/manager/plugins/organisms/dos/Organisms.js index 11273d9..659788d 100644 --- a/client/src/manager/plugins/organisms/dos/Organisms.js +++ b/client/src/manager/plugins/organisms/dos/Organisms.js @@ -226,8 +226,10 @@ class Organisms extends BaseOrganisms { * @param {Object} ret Return object */ _onStepIn(x, y, orgJson, ret) { - if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent) && this.createOrg(x, y)) { - const org = this.organisms.last.val; + if (ret.ret = this.world.isFree(x, y) && this.organisms.size < (OConfig.orgMaxOrgs + OConfig.orgMaxOrgs * OConfig.orgStepOverflowPercent)) { + const item = this.createOrg(x, y); + if (item === false) {return} + const org = item.val; org.unserialize(orgJson); const energy = (org.energy * OConfig.orgStepEnergySpendPercent + .5) << 0; // diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 0767836..27a3ef1 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -93,7 +93,7 @@ ClientConfig.init({ * all energy in a world after which clever energy will turn on (be added to the * world again). */ - worldEnergyMinPercent: .3, + worldEnergyMinPercent: .28, /** * {Number} Percent of stones in a world. Percent from world size: * stoneAmount = worldStonesPercent * worldWidth * worldHeight diff --git a/common/src/Queue.js b/common/src/Queue.js index 9c22dec..58caf91 100644 --- a/common/src/Queue.js +++ b/common/src/Queue.js @@ -50,6 +50,29 @@ class Queue { this._first.val = val; } + /** + * The same like add(), but inserts after specified item in a queue + * @param {Object} item Item, after which val will be inserted + * @param {*} val Value to insert + * @return {Object} Inserted item + */ + addAfter(item, val) { + if (item === this._last) {this.add(val); return this._last} + if (this._size++ > 0) { + const newItem = { + prev: item, + next: item.next, + val + }; + item.next.prev = newItem; + item.next = newItem; + return newItem; + } + this._first.val = val; + + return this._first; + } + /** * Removes specified item from the queue. 'item' parameter is not * the same as value inside this item. Remember remove position may From 41a437efc666ed16c02e90c33366967211629f6a Mon Sep 17 00:00:00 2001 From: DeadbraiN Date: Tue, 3 Apr 2018 13:41:03 +0300 Subject: [PATCH 291/291] fixed an issue with infinite alive period and huge amount of mutations fixed an issue with incorrect color of organisms in case of infinite alive period fixed random distribution of organisms by age optimized _randOrg() method --- .../src/manager/plugins/organisms/Config.js | 20 +++++----- .../src/manager/plugins/organisms/Mutator.js | 7 +++- .../src/manager/plugins/organisms/Organism.js | 2 +- .../manager/plugins/organisms/Organisms.js | 37 +++++++++++-------- client/src/share/Config.js | 4 +- common/src/Observer.js | 3 +- 6 files changed, 42 insertions(+), 31 deletions(-) diff --git a/client/src/manager/plugins/organisms/Config.js b/client/src/manager/plugins/organisms/Config.js index ed7ac4d..931954f 100644 --- a/client/src/manager/plugins/organisms/Config.js +++ b/client/src/manager/plugins/organisms/Config.js @@ -15,12 +15,12 @@ const Config = { * implemented. See Operators.operators getter for details. Values may be float. */ orgOperatorWeights: [ - .001, .001, .00001, .00000001, .0001, // var, const, if, loop, operator, - .0001, .2, .2, .2, .2, // lookAt, eatLeft, eatRight, eatUp, eatDown, - 2, 2, 2, 2, // stepLeft, stepRight, stepUp, stepDown, - .001, .001, // fromMem, toMem, - .0001, .0001, // myX, myY, - .001, .001, .001, .001 // checkLeft, checkRight, checkUp, checkDown + .0001, .0001, .00001, .00000001, .0001, // var, const, if, loop, operator, + .00001, 2, 2, 2, 2, // lookAt, eatLeft, eatRight, eatUp, eatDown, + 2, 2, 2, 2, // stepLeft, stepRight, stepUp, stepDown, + .001, .001, // fromMem, toMem, + .0001, .0001, // myX, myY, + .001, .001, .001, .001 // checkLeft, checkRight, checkUp, checkDown ], /** * {Array} Probabilities which used, when mutator decides what to do: @@ -52,18 +52,18 @@ const Config = { * {Number} Minimum age for cloning. Before that, cloning is impossible. It should * be less then orgAlivePeriod config */ - orgCloneMinAge: 300, + orgCloneMinAge: 3000, /** * {Number} Minimum energy for cloning */ - orgCloneMinEnergy: 2000000, + orgCloneMinEnergy: 20000000, /** * {Boolean} If true, then random organism will be killed after new one has * cloned and amount of organisms is greater then orgMaxOrgs config. false * mean, that new organism will not be cloned, if amount of organisms is >= * orgMaxOrgs config. */ - orgKillOnClone: false, + orgKillOnClone: true, /** * {Number} Amount of iterations between tournament. During tournament one * organism (looser) will be killed @@ -100,7 +100,7 @@ const Config = { * {Number} Amount of iterations when organism is alive. It will die after * this period. If 0, then will not be used and organism may leave forever */ - orgAlivePeriod: 1000, + orgAlivePeriod: 0, /** * {Number} Size of organism stack (internal memory) in bits. Real amount of * organism's internal memory will be 2^orgMemBits. Example: if orgMemBits=3, diff --git a/client/src/manager/plugins/organisms/Mutator.js b/client/src/manager/plugins/organisms/Mutator.js index 65de19c..e7152a5 100644 --- a/client/src/manager/plugins/organisms/Mutator.js +++ b/client/src/manager/plugins/organisms/Mutator.js @@ -15,6 +15,11 @@ const Helper = require('./../../../../../common/src/Helper'); const Num = require('./../../../vm/Num'); const ADD_MUTAION_INDEX = 6; +/** + * {Number} Default alive period, which is used if orgAlivePeriod + * config is set to zero + */ +const MAX_ALIVE_PERIOD = 10000; class Mutator { static _onChange(org) { @@ -54,7 +59,7 @@ class Mutator { static _onMutationPeriod(org) { if (!OConfig.orgRainPerOrg) {return} - org.mutationPeriod = Helper.rand(OConfig.orgAlivePeriod - 1) + 1; + org.mutationPeriod = OConfig.orgAlivePeriod < 1 ? Helper.rand(MAX_ALIVE_PERIOD) + 1 : Helper.rand(OConfig.orgAlivePeriod - 1) + 1; org.changes++; } diff --git a/client/src/manager/plugins/organisms/Organism.js b/client/src/manager/plugins/organisms/Organism.js index c8c7224..c1a7ff2 100644 --- a/client/src/manager/plugins/organisms/Organism.js +++ b/client/src/manager/plugins/organisms/Organism.js @@ -236,7 +236,7 @@ class Organism extends Observer { } _updateColor() { - this._color = Organism.getColor(this._iterations * (MAX_COLORS / OConfig.orgAlivePeriod)); + this._color = Organism.getColor(OConfig.orgAlivePeriod === 0 ? MAX_COLORS : this._iterations * (MAX_COLORS / OConfig.orgAlivePeriod)); } _updateClone() { diff --git a/client/src/manager/plugins/organisms/Organisms.js b/client/src/manager/plugins/organisms/Organisms.js index 771fda9..28e0631 100644 --- a/client/src/manager/plugins/organisms/Organisms.js +++ b/client/src/manager/plugins/organisms/Organisms.js @@ -16,6 +16,10 @@ const ORG_EVENTS = require('./../../../../src/manager/plugins/organisms/Organi //const Backup = require('./../backup/Backup'); const Mutator = require('./Mutator'); const Num = require('./../../../vm/Num'); +/** + * {Number} Random range for selection of random organism from a Queue + */ +const RAND_RANGE = 5; // TODO: inherit this class from Configurable class Organisms extends Configurable { @@ -98,7 +102,6 @@ class Organisms extends Configurable { this._maxEnergy = this._oldMaxEnergy; this._oldMaxEnergy = 0; } - org.maxEnergy = this._maxEnergy; } addOrgHandlers(org) { @@ -131,6 +134,7 @@ class Organisms extends Configurable { createOrg(x, y, parent = null) { if (x === -1) {return false} + this._randOrg(); const item = this.organisms.addAfter(this.randOrgItem, null); let org = this.createEmptyOrg(++this._orgId + '', x, y, item, parent); @@ -148,8 +152,8 @@ class Organisms extends Configurable { * Returns random organism of current population * @return {Organism|null} */ - randOrg() { - const offs = Helper.rand(this.organisms.size) + 1; + _randOrg() { + const offs = Helper.rand(RAND_RANGE) + 1; let item = this.randOrgItem; for (let i = 0; i < offs; i++) { @@ -173,7 +177,7 @@ class Organisms extends Configurable { while (org = item && item.val) { org.run(); - org.energy > 0 && this.onOrganism(org); + this.onOrganism(org); item = item.next; } @@ -187,8 +191,8 @@ class Organisms extends Configurable { } _tournament(org1 = null, org2 = null) { - org1 = org1 || this.randOrg(); - org2 = org2 || this.randOrg(); + org1 = org1 || this._randOrg(); + org2 = org2 || this._randOrg(); if (org1.energy < 1 && org2.energy < 1) {return false} if ((org2.energy > 0 && org1.energy < 1) || this.compare(org2, org1)) { @@ -293,12 +297,12 @@ class Organisms extends Configurable { //const orgAmount = this.organisms.size; //if (OConfig.orgKillOnClone && orgAmount >= maxOrgs) {this._killInTour()} - //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this.randOrg().destroy()} + //if (orgAmount >= maxOrgs && (OConfig.orgKillOnClone || Math.random() <= (org.energy / org.vm.size) / this._maxEnergy)) {this._randOrg().destroy()} // if (this.organisms.size >= OConfig.orgMaxOrgs && Math.random() <= ((org.energy / 10000000000000) * (org.iterations / OConfig.orgAlivePeriod))) { - // this.randOrg().destroy(); + // this._randOrg().destroy(); // } //if (this.organisms.size < maxOrgs) {this._clone(org)} - //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this.randOrg().destroy()} + //if (this.organisms.size >= maxOrgs && Math.random() <= (org.energy / org.vm.size) / this._maxEnergy) {this._randOrg().destroy()} // // This is very important part of application! Cloning should be available only if // amount of organisms is less then maximum or if current organism has ate other just @@ -307,13 +311,16 @@ class Organisms extends Configurable { // organisms before cloning. They should kill each other to have a possibility // to clone them. // - if (OConfig.orgKillOnClone && this.organisms.size >= OConfig.orgMaxOrgs) {this.randOrg().destroy()} + if (OConfig.orgKillOnClone && this.organisms.size >= OConfig.orgMaxOrgs) { + const randOrg = this._randOrg(); + if (randOrg !== org && Math.random() <= org.iterations / OConfig.orgAlivePeriod) {randOrg.destroy()} + } if (this.organisms.size < OConfig.orgMaxOrgs) {this._clone(org)} } _killInTour() { - let org1 = this.randOrg(); - let org2 = this.randOrg(); + let org1 = this._randOrg(); + let org2 = this._randOrg(); if (org1.energy < 1 || org2.energy < 1 || org1 === org2 || this.organisms.size < 1) {return false} const winner = this._tournament(org1, org2); if (winner === false) {return false} @@ -338,7 +345,7 @@ class Organisms extends Configurable { _updateRandomOrgs(counter) { if (counter % OConfig.orgRandomOrgPeriod !== 0 || OConfig.orgRandomOrgPeriod === 0 || this.organisms.size < 1) {return false} - const vm = this.randOrg().vm; + const vm = this._randOrg().vm; const size = Helper.rand(vm.size) + 1; const pos = Helper.rand(vm.size - size); @@ -354,8 +361,8 @@ class Organisms extends Configurable { // We have to have a possibility to crossover not only with best // organisms, but with low fit also // - let org1 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); - let org2 = Helper.rand(2) === 0 ? this._tournament() : this.randOrg(); + let org1 = Helper.rand(2) === 0 ? this._tournament() : this._randOrg(); + let org2 = Helper.rand(2) === 0 ? this._tournament() : this._randOrg(); if (org1 === false || org2 === false || org1.energy < 1 || org2.energy < 1) {return false} this._crossover(org1, org2); diff --git a/client/src/share/Config.js b/client/src/share/Config.js index 27a3ef1..d70a4bb 100644 --- a/client/src/share/Config.js +++ b/client/src/share/Config.js @@ -75,7 +75,7 @@ ClientConfig.init({ /** * {Number} size of one clever energy block in dots */ - worldEnergyBlockSize: 20, + worldEnergyBlockSize: 10, /** * {Number} Index of energy color. Starts from 0. Ends with 4000. See Organism.MAX_COLORS * constant for details @@ -87,7 +87,7 @@ ClientConfig.init({ * be less then worldEnergyMinPercent. These two configs create cyclical * energy adding to the world. */ - worldEnergyMaxPercent: .7, + worldEnergyMaxPercent: .3, /** * {Number} Opposite to worldEnergyMaxPercent. Sets minimum percent from * all energy in a world after which clever energy will turn on (be added to the diff --git a/common/src/Observer.js b/common/src/Observer.js index 97e879c..6e525a0 100644 --- a/common/src/Observer.js +++ b/common/src/Observer.js @@ -53,9 +53,8 @@ class Observer { /** * This method is a most frequently called one. So we have to * optimize it as much as possible - * @param {Number} event Event number + * @param {Number} event Event number. Not string * @param {*} args List of arguments - * @param args */ fire(event, ...args) { const handlers = this._handlers[event] || {};