138 Commits

Author SHA1 Message Date
c072842c3a Merge pull request #44 from BlackMATov/dev
Dev
2026-02-13 23:24:38 +07:00
BlackMATov
39c0b988b5 v1.10.0 2026-02-13 23:18:20 +07:00
BlackMATov
766f7b92be update README 2026-02-13 21:13:51 +07:00
BlackMATov
e364aaab37 update teal definitions 2026-02-13 08:07:14 +07:00
BlackMATov
b941baf6bb additional nr/to spawn/lookup tests 2026-02-13 07:55:25 +07:00
BlackMATov
8b77b45421 fix new discards in tests 2026-02-13 07:36:52 +07:00
BlackMATov
f9943c9fca nr/to multi_spawn/lookup versions 2026-02-13 07:35:35 +07:00
BlackMATov
eb853c8392 update README 2026-02-09 09:52:42 +07:00
BlackMATov
b38594fdfc Merge branch 'feature/lookup' into dev 2026-02-09 09:49:15 +07:00
BlackMATov
655c0aef07 update README 2026-02-09 09:47:18 +07:00
BlackMATov
2c4cb179bc (multi_)lookup first impl 2026-02-09 09:27:00 +07:00
BlackMATov
e49a339f5e dummy lookup functions and name hooks 2026-02-08 06:56:20 +07:00
BlackMATov
340feacf55 Merge branch 'dev' into feature/lookup 2026-02-08 06:48:33 +07:00
BlackMATov
caa8cc5625 move container functions to separated local tables 2026-02-08 06:48:17 +07:00
BlackMATov
cd1a583682 lookup api and basic tests 2026-02-08 06:16:00 +07:00
BlackMATov
5efd9ab2ae ensure that entity_chunks and entity_places have only array-parts 2026-02-06 17:36:09 +07:00
BlackMATov
b7419eec5d do not clear array part of builder component table 2026-02-05 15:30:50 +07:00
BlackMATov
287f03ef87 enable the debug mode for all tests 2026-02-03 06:12:29 +07:00
BlackMATov
260f841a3b fix some package usage 2026-02-03 06:11:58 +07:00
BlackMATov
d1105c15ad non-shrinking version of garbage collection 2026-02-02 20:46:50 +07:00
BlackMATov
a1440f26df size hint for some internal list functions 2026-02-02 17:32:07 +07:00
f6b8844a82 Merge pull request #40 from BlackMATov/dev
Dev
2026-02-02 08:30:39 +07:00
BlackMATov
7ce5ee924c v1.9.0 2026-02-02 08:28:27 +07:00
BlackMATov
539a62c8a8 shrink table pools on gc 2026-02-02 08:21:40 +07:00
BlackMATov
63a7ab5c79 update roadmap 2026-02-02 08:21:29 +07:00
BlackMATov
9a9fb1ddb9 Merge branch 'feature/determinism' into dev 2026-02-02 07:39:44 +07:00
BlackMATov
7b44740803 deterministic chunk ordering 2026-02-02 07:38:02 +07:00
BlackMATov
b0d035c0d4 migrate root chunks map to separated set/list 2026-01-28 02:26:06 +07:00
BlackMATov
8d88d55267 Merge branch 'feature/id_opts' into dev 2026-01-27 08:22:55 +07:00
BlackMATov
b774abf63c update readme 2026-01-27 08:22:39 +07:00
BlackMATov
4a018f4c40 specialize clean/destroy functions 2026-01-27 08:06:12 +07:00
BlackMATov
39c20f13dd clear hash part pool tables only when needed 2026-01-26 23:40:10 +07:00
BlackMATov
ce864b7433 acquire temp tables only on-demand 2026-01-26 21:16:13 +07:00
BlackMATov
04c9e4aaeb new id bmarks 2026-01-26 17:46:22 +07:00
e48bdf0511 Merge pull request #39 from BlackMATov/dev
Dev
2026-01-18 20:27:35 +07:00
BlackMATov
e9824a4776 v1.8.0 2026-01-18 20:24:53 +07:00
BlackMATov
c3760c40bf update README 2026-01-18 20:20:13 +07:00
BlackMATov
a2a4fc56e3 Merge branch 'feature/mappers' into dev 2026-01-18 19:30:08 +07:00
BlackMATov
21d5091d14 first mappers impl 2026-01-18 19:28:12 +07:00
BlackMATov
18ee0d9a12 Merge branch 'feature/realloc' into dev 2026-01-16 07:27:02 +07:00
BlackMATov
12c86ca679 update README 2026-01-16 07:24:38 +07:00
BlackMATov
a0f252f47c additional realloc checks 2026-01-16 06:14:59 +07:00
BlackMATov
b17118544d little cleanup 2026-01-16 04:17:09 +07:00
BlackMATov
b9cdbe961b custom storage free semantic 2026-01-16 04:12:17 +07:00
BlackMATov
4f78c8245c update roadmap 2026-01-14 16:12:24 +07:00
BlackMATov
a7e5652ad4 update readme and teal defs (REALLOC/COMPMOVE fragments) 2026-01-13 05:11:04 +07:00
BlackMATov
c52f708184 fix batch optimizations with reallocs 2026-01-13 04:47:16 +07:00
BlackMATov
e75ddef396 first realloc/compmove imp 2026-01-13 01:14:50 +07:00
BlackMATov
c9bfb26748 dummy chunk entity capacity 2026-01-12 16:29:44 +07:00
BlackMATov
3a3abbd2fd dummy realloc fragments 2026-01-12 16:28:32 +07:00
a945401e9b Merge pull request #37 from BlackMATov/dev
Dev
2026-01-11 21:19:41 +07:00
BlackMATov
d9c9b4cf85 v1.7.0 2026-01-11 21:16:36 +07:00
BlackMATov
20c94a0b72 Merge branch 'feature/variants' into dev 2026-01-11 21:11:45 +07:00
BlackMATov
e396c320ee update readme and teal defs (VARIANTS fragment) 2026-01-11 21:08:22 +07:00
BlackMATov
52c898f912 rename eithers to variants 2026-01-11 20:49:09 +07:00
BlackMATov
a5319351c1 first eithers impl 2026-01-11 20:33:17 +07:00
BlackMATov
c9f4a74518 dummy eithers fragment 2026-01-06 20:23:22 +07:00
BlackMATov
c29092c3e1 update embedded xpcall.lua to v1.0.1 2026-01-04 09:32:08 +07:00
BlackMATov
a0a4a20c35 Happy New Year! 🥳 2026-01-03 15:52:01 +07:00
BlackMATov
2f8b0b0ef3 Merge branch 'feature/process_with' into dev
https://github.com/BlackMATov/evolved.lua/issues/34
2026-01-03 15:48:40 +07:00
BlackMATov
5e0170b4e8 new evolved.process_with function impl 2026-01-03 15:42:59 +07:00
a1423ea9ee Merge pull request #33 from BlackMATov/dev
Dev
2025-12-28 06:48:21 +07:00
BlackMATov
d42c0cf3db v1.6.0 2025-12-28 06:46:15 +07:00
BlackMATov
723a65ca7f added the new evolved.depth function 2025-12-28 06:36:11 +07:00
BlackMATov
72fc524fe0 little style fixes 2025-12-28 06:02:28 +07:00
BlackMATov
a8d1d84bed add more lua versions to CI 2025-12-25 16:02:27 +07:00
BlackMATov
568cec4012 table.new/create cleanup 2025-12-25 15:55:15 +07:00
BlackMATov
f175a25f1a little style fixes 2025-12-24 15:03:45 +07:00
BlackMATov
856b9c665d update changelog 2025-12-18 01:27:35 +07:00
BlackMATov
8e2a34f2f6 optimize setting of fragments with required fragments 2025-12-18 00:14:10 +07:00
BlackMATov
47dd1bb30a optimize spawning/cloning of entities with required fragments 2025-12-17 07:31:32 +07:00
12a720bd9e Merge pull request #31 from BlackMATov/dev
Dev
2025-11-24 13:49:59 +07:00
BlackMATov
5895c6ee8f v1.5.0 2025-11-24 13:45:55 +07:00
BlackMATov
1c02ba5468 little love2d example 2025-11-24 13:35:34 +07:00
BlackMATov
760b477564 update changelog 2025-11-21 06:31:42 +07:00
BlackMATov
fc910881bd cache defaults/duplicates per chunk, use it for spawn/clone ops 2025-11-21 05:37:14 +07:00
BlackMATov
71a7c84a67 add spawn/clone with defaults bmarks 2025-11-20 16:19:13 +07:00
BlackMATov
582a09a6db additional spawn/clone tests 2025-11-20 05:00:52 +07:00
BlackMATov
de73881f63 improve performance of the clone operations 2025-11-19 08:51:26 +07:00
BlackMATov
55e444ca63 improve performance of the spawn operations 2025-11-19 02:23:48 +07:00
BlackMATov
e499c701ef add defer clone bmarks 2025-11-12 23:44:34 +07:00
BlackMATov
789f167bf4 add defer spawn bmarks 2025-11-12 16:47:38 +07:00
BlackMATov
00367ce07e Merge branch 'feature/teal' into dev 2025-11-08 01:34:29 +07:00
BlackMATov
07902eb184 teal definitions cleanup 2025-11-07 23:26:45 +07:00
ecdbfe660f Merge pull request #30 from p0sel0k/main 2025-11-07 16:03:22 +07:00
p0sel0k
cfd68767cf fix: set and batch_set component argument should be optional 2025-11-04 21:57:00 +03:00
p0sel0k
f1ba9ab909 fix: replace number type with integer; EachState\ExecuteState records 2025-11-04 18:56:02 +03:00
BlackMATov
77ff3e77db readme: internal fragments
https://github.com/BlackMATov/evolved.lua/issues/28
2025-11-04 21:00:22 +07:00
p0sel0k
825eba5328 fix: remove teal types for internal usage 2025-11-04 10:06:01 +03:00
p0sel0k
67002503ed fix: removed IComponent and added generics for functions and hooks that take Component as a single argument 2025-11-03 11:57:18 +03:00
p0sel0k
1bb0089e9f fix: functions arguments naming 2025-11-02 21:21:25 +03:00
p0sel0k
dc642f5294 fix: fixes after review 2025-11-02 21:12:26 +03:00
p0sel0k
a81a8646e9 fix: wrong file name 2025-10-29 19:29:56 +03:00
p0sel0k
aa6d2c1c48 feat: add Teal language definitions 2025-10-29 19:24:07 +03:00
BlackMATov
5fe48de890 little speed up of exclude-only queries 2025-10-29 22:57:58 +07:00
0d7adcb5fd Merge pull request #27 from BlackMATov/dev
Dev
2025-10-20 16:16:39 +07:00
BlackMATov
f48f1bb290 v1.4.0 2025-10-20 16:11:03 +07:00
BlackMATov
6f1a85165f more tests 2025-10-16 06:22:30 +07:00
BlackMATov
bd87e593e9 root directory cleanup 2025-10-14 17:50:51 +07:00
BlackMATov
0eac310fd5 style fixes 2025-10-12 23:35:28 +07:00
BlackMATov
22cedd26bb remove some of the specialized defer functions in favor of the universal defer_call_hook 2025-10-12 07:04:44 +07:00
BlackMATov
d298be4188 ON_REMOVE hooks are now invoked before the fragment is actually removed from the entity
issue: https://github.com/BlackMATov/evolved.lua/issues/26
2025-10-12 06:46:43 +07:00
BlackMATov
24933e6a04 little internal hooks refactoring 2025-10-08 16:18:49 +07:00
BlackMATov
6841bb42fe style fixes 2025-10-07 22:56:29 +07:00
BlackMATov
dc912eb6da the universal builder:build/multi_build methods 2025-10-06 19:05:16 +07:00
BlackMATov
8d3c4633fb little coverage upping 2025-10-06 16:53:53 +07:00
BlackMATov
8704fb0c39 update changelog 2025-10-06 04:46:14 +07:00
BlackMATov
86c9ef7cf2 caching exclude-only queries was a mistake 2025-10-06 04:38:06 +07:00
BlackMATov
bd5f9bb61f cache exclude-only queries too 2025-10-06 02:53:38 +07:00
BlackMATov
cfa5dc7a9f lazy query chunks updating 2025-10-06 01:46:54 +07:00
BlackMATov
243adc1a93 fix query cache reset 2025-10-05 09:13:59 +07:00
BlackMATov
cf19fba9e4 cache query major chunks: first impl 2025-10-05 08:59:07 +07:00
BlackMATov
784b9c6a15 delele some unnecessary checks 2025-09-29 15:20:37 +07:00
2903b077fe Merge pull request #24 from BlackMATov/dev
Dev
2025-09-26 17:30:35 +07:00
BlackMATov
d3b14a6741 v1.3.0 2025-09-26 17:27:49 +07:00
BlackMATov
fdf5a03a02 improve performance of builders that are used for spawning multiple times 2025-09-26 17:21:50 +07:00
BlackMATov
9221da6ea7 slightly improve required fragments perf 2025-09-24 18:16:01 +07:00
BlackMATov
0aa57f6b5b benchmarks refactoring 2 2025-09-24 00:51:25 +07:00
BlackMATov
7e38e43d7c benchmarks refactoring 2025-09-23 17:37:29 +07:00
BlackMATov
b1b627b677 improve perf of cloning prefabs with many unique fragments 2025-09-23 07:53:11 +07:00
BlackMATov
281866cf6e set/assign hooks are not invoked for tags on override operations anymore 2025-09-23 07:24:26 +07:00
BlackMATov
4ad7fec26d update readme 2025-09-23 05:05:30 +07:00
BlackMATov
f15118be05 the new evolved.locate public function
ref: #23
2025-09-23 04:58:10 +07:00
BlackMATov
964ea45f48 use xpcall to process systems 2025-09-22 21:27:57 +07:00
BlackMATov
b2c08e1127 cancel deferring ops in systems on error 2025-09-22 05:51:21 +07:00
BlackMATov
2250bd64ce the new evolved.cancel public function 2025-09-22 02:34:37 +07:00
BlackMATov
e564be46fb collect garbage from old bytecode 2025-09-22 01:56:08 +07:00
BlackMATov
521ad94278 the internal garbage collector now collects more garbage 2025-09-20 03:11:12 +07:00
BlackMATov
7f6909e48c remove some unused code about pinned chunks 2025-09-20 01:53:29 +07:00
BlackMATov
ec745f6ad7 Merge branch 'feature/schemes' into dev 2025-09-19 19:51:02 +07:00
BlackMATov
b3eec59f8b update readme 2025-09-19 19:50:50 +07:00
BlackMATov
1635dd66b1 remove schemes temporary 2025-09-19 18:58:18 +07:00
BlackMATov
b420085ed5 proof of concept ffi component storages
fast batch ops storage swapping was temporary removed
2025-09-19 07:04:19 +07:00
BlackMATov
6d5f810d45 experimental scheme creation 2025-09-15 17:56:44 +07:00
BlackMATov
5447f50090 dummy SCHEME class and readme 2025-09-12 05:58:41 +07:00
BlackMATov
e6d79dc600 Merge branch 'dev' into feature/schemes 2025-09-12 05:45:33 +07:00
BlackMATov
eb31ed247b little test fixes 2025-09-08 17:41:18 +07:00
BlackMATov
9400401161 dummy SCHEME fragment trait 2025-09-03 15:07:32 +07:00
60 changed files with 11339 additions and 4105 deletions

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- uses: leafo/gh-actions-lua@v11
- uses: leafo/gh-actions-lua@v12
with:
luaVersion: ${{matrix.lua_version}}
- run: |

21
.github/workflows/lua5.2.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: lua5.2
on: [push, pull_request]
jobs:
build:
runs-on: ${{matrix.operating_system}}
strategy:
fail-fast: false
matrix:
lua_version: ["5.2"]
operating_system: ["ubuntu-latest", "macos-latest", "windows-latest"]
name: ${{matrix.operating_system}}-${{matrix.lua_version}}
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- uses: leafo/gh-actions-lua@v12
with:
luaVersion: ${{matrix.lua_version}}
- run: |
lua ./develop/all.lua

21
.github/workflows/lua5.3.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: lua5.3
on: [push, pull_request]
jobs:
build:
runs-on: ${{matrix.operating_system}}
strategy:
fail-fast: false
matrix:
lua_version: ["5.3"]
operating_system: ["ubuntu-latest", "macos-latest", "windows-latest"]
name: ${{matrix.operating_system}}-${{matrix.lua_version}}
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- uses: leafo/gh-actions-lua@v12
with:
luaVersion: ${{matrix.lua_version}}
- run: |
lua ./develop/all.lua

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- uses: leafo/gh-actions-lua@v11
- uses: leafo/gh-actions-lua@v12
with:
luaVersion: ${{matrix.lua_version}}
- run: |

View File

@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- uses: leafo/gh-actions-lua@v11
- uses: leafo/gh-actions-lua@v12
with:
luaVersion: ${{matrix.lua_version}}
- run: |

View File

@@ -28,6 +28,9 @@
"ignoreDir": [
".vscode",
"develop/3rdparty"
],
"library": [
"${3rd}/love2d/library"
]
}
}

38
.vscode/launch.json vendored
View File

@@ -10,6 +10,24 @@
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved All (lua5.2)",
"type": "lua-local",
"request": "launch",
"program": {
"lua": "lua5.2",
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved All (lua5.3)",
"type": "lua-local",
"request": "launch",
"program": {
"lua": "lua5.3",
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved All (lua5.4)",
"type": "lua-local",
@@ -19,6 +37,15 @@
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved All (lua5.5)",
"type": "lua-local",
"request": "launch",
"program": {
"lua": "lua5.5",
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved All (luajit)",
"type": "lua-local",
@@ -27,6 +54,17 @@
"lua": "luajit",
"file": "${workspaceFolder}/develop/all.lua"
}
},
{
"name": "Launch Evolved Example (LÖVE)",
"type": "lua-local",
"request": "launch",
"program": {
"command": "love"
},
"args": [
"${workspaceFolder}/example"
]
}
]
}

View File

@@ -1,5 +1,5 @@
{
"[json][jsonc][lua][markdown][yaml]": {
"[json][jsonc][lua][markdown][teal][yaml]": {
"editor.formatOnSave": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
@@ -8,7 +8,6 @@
"markdown.extension.toc.levels": "2..6",
"markdown.extension.toc.omittedFromToc": {
"README.md": [
"# Changelog",
"# API Reference"
]
}

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (C) 2024-2025, by Matvey Cherevko (blackmatov@gmail.com)
Copyright (C) 2024-2026, by Matvey Cherevko (blackmatov@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

911
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
# Roadmap
## Backlog
- Improve the performance of required fragments by caching first-level required chunks.
- Improve the performance of builders that are used multiple times by caching hint chunks.
- Queries can cache major chunks to avoid finding them every time.
- Add a function to shrink storages to free unused memory.
- observers and events
- add INDEX fragment trait
- use compact prefix-tree for chunks
- optional ffi component storages
## Thoughts
- We can return deferred status from modifying operations and spawn/clone methods.
- Should we make one builder:build method instead of :spawn and :clone?
- Should we cache the result of without_unique_fragments to clone faster?

View File

@@ -17,6 +17,7 @@
1. Insert the new function into the `evolved` table in `evolved.lua`.
2. Create tests for the function in `develop/testing/function_name_tests.lua`.
3. Add the new test to `develop/all.lua`.
4. Document the function in the **Cheat Sheet** and **API Reference** sections of `README.md`.
5. Provide a description in the **Overview** section of `README.md`.
6. Describe the update in the **Changelog** section of `README.md`.
4. Update the Teal type definitions in `evolved.d.tl`.
5. Document the function in the **Cheat Sheet** and **API Reference** sections of `README.md`.
6. Provide a description in the **Overview** section of `README.md`.
7. Describe the update in the **Changelog** section of `README.md`.

16
develop/ROADMAP.md Normal file
View File

@@ -0,0 +1,16 @@
# Roadmap
## Backlog
- observers and events
- add INDEX fragment trait
- use compact prefix-tree for chunks
## Thoughts
- We should have a way to not copy components on deferred spawn/clone
- Basic default component value as true looks awful, should we use something else?
## Known Issues
- Errors in hooks or rellocs/compmoves/mappers are cannot be handled properly right now

View File

@@ -1,23 +1,35 @@
require 'develop.samples.systems'
require 'develop.testing.build_tests'
require 'develop.testing.cancel_tests'
require 'develop.testing.clone_tests'
require 'develop.testing.depth_tests'
require 'develop.testing.destroy_tests'
require 'develop.testing.locate_tests'
require 'develop.testing.lookup_tests'
require 'develop.testing.main_tests'
require 'develop.testing.mappers_tests'
require 'develop.testing.multi_spawn_tests'
require 'develop.testing.name_tests'
require 'develop.testing.process_with_tests'
require 'develop.testing.realloc_tests'
require 'develop.testing.requires_fragment_tests'
require 'develop.testing.spawn_tests'
require 'develop.testing.system_as_query_tests'
require 'develop.benchmarks.multi_clone_bmarks'
require 'develop.benchmarks.multi_spawn_bmarks'
require 'develop.untests'
require 'develop.unbench'
require 'develop.usbench'
require 'develop.benchmarks.clone_bmarks'
require 'develop.benchmarks.common_bmarks'
require 'develop.benchmarks.destroy_bmarks'
require 'develop.benchmarks.migration_bmarks'
require 'develop.benchmarks.process_bmarks'
require 'develop.benchmarks.spawn_bmarks'
require 'develop.benchmarks.table_bmarks'
local basics = require 'develop.basics'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.execute_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.explicit_fuzz'
@@ -27,3 +39,5 @@ print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.requires_fuzz'
print '----------------------------------------'
basics.describe_fuzz 'develop.fuzzing.unique_fuzz'
print 'All tests passed.'

View File

@@ -0,0 +1,535 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
evo.set(D1, evo.DUPLICATE, function(v) return not v end)
evo.set(D2, evo.DUPLICATE, function(v) return not v end)
evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF1] = true }
evo.remove(prefab, F1)
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 1 required component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
evo.remove(prefab, F1, F2, F3)
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 3 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD123] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
evo.remove(prefab, F1, F2, F3, F4, F5)
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Defer Clone | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone With Defaults | %d entities with 5 required components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [RD12345] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [D1] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF1] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF1] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 required component', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RD1] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF123] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF123] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 3 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RD123] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF12345] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
multi_clone_nr(N, prefab)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 5 required components', N),
function()
local multi_clone_nr = evo.multi_clone_nr
local prefab = evo.spawn { [RD12345] = true }
multi_clone_nr(N, prefab)
evo.batch_destroy(QD1)
end)

View File

@@ -0,0 +1,340 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
local tiny = require 'develop.3rdparty.tiny'
evo.debug_mode(false)
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Entity Cycle | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0 })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) world:addEntity({ b = e.a }) end
A.postProcess = function(_) world:refresh() end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) world:removeEntity(e) end
B.postProcess = function(_) world:refresh() end
world:addSystem(A)
world:addSystem(B)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Entity Cycle | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local query_a = evo.builder():set(world):include(a):spawn()
local query_b = evo.builder():set(world):include(b):spawn()
local prefab_a = evo.builder():prefab():set(world):set(a, 0):spawn()
local prefab_b = evo.builder():prefab():set(world):set(b, 0):spawn()
evo.multi_clone_nr(N, prefab_a)
evo.builder()
:set(world):group(world):query(query_a)
:execute(function(chunk, _, entity_count)
local as = chunk:components(a)
local entity_bs = evo.multi_clone(entity_count, prefab_b)
for i = 1, entity_count do evo.set(entity_bs[i], b, as[i]) end
end):spawn()
evo.builder()
:set(world):group(world):query(query_b)
:prologue(function()
evo.batch_destroy(query_b)
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Simple Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0, b = 0 })
world:addEntity({ a = 0, b = 0, c = 0 })
world:addEntity({ a = 0, b = 0, c = 0, d = 0 })
world:addEntity({ a = 0, b = 0, c = 0, e = 0 })
end
local AB = tiny.processingSystem()
AB.filter = tiny.requireAll('a', 'b')
AB.process = function(_, e) e.a, e.b = e.b, e.a end
local CD = tiny.processingSystem()
CD.filter = tiny.requireAll('c', 'd')
CD.process = function(_, e) e.c, e.d = e.d, e.c end
local CE = tiny.processingSystem()
CE.filter = tiny.requireAll('c', 'e')
CE.process = function(_, e) e.c, e.e = e.e, e.c end
world:addSystem(AB)
world:addSystem(CD)
world:addSystem(CE)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Simple Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local c = evo.builder():set(world):spawn()
local d = evo.builder():set(world):spawn()
local e = evo.builder():set(world):spawn()
local query_ab = evo.builder():set(world):include(a, b):spawn()
local query_cd = evo.builder():set(world):include(c, d):spawn()
local query_ce = evo.builder():set(world):include(c, e):spawn()
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0 })
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_ab)
:execute(function(chunk, _, entity_count)
local as, bs = chunk:components(a, b)
for i = 1, entity_count do as[i], bs[i] = bs[i], as[i] end
end):spawn()
evo.builder()
:set(world):group(world):query(query_cd)
:execute(function(chunk, _, entity_count)
local cs, ds = chunk:components(c, d)
for i = 1, entity_count do cs[i], ds[i] = ds[i], cs[i] end
end):spawn()
evo.builder()
:set(world):group(world):query(query_ce)
:execute(function(chunk, _, entity_count)
local cs, es = chunk:components(c, e)
for i = 1, entity_count do cs[i], es[i] = es[i], cs[i] end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Packed Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
for _ = 1, N do
world:addEntity({ a = 0, b = 0, c = 0, d = 0, e = 0 })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) e.a = e.a * 2 end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) e.b = e.b * 2 end
local C = tiny.processingSystem()
C.filter = tiny.requireAll('c')
C.process = function(_, e) e.c = e.c * 2 end
local D = tiny.processingSystem()
D.filter = tiny.requireAll('d')
D.process = function(_, e) e.d = e.d * 2 end
local E = tiny.processingSystem()
E.filter = tiny.requireAll('e')
E.process = function(_, e) e.e = e.e * 2 end
world:addSystem(A)
world:addSystem(B)
world:addSystem(C)
world:addSystem(D)
world:addSystem(E)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Packed Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local a = evo.builder():set(world):spawn()
local b = evo.builder():set(world):spawn()
local c = evo.builder():set(world):spawn()
local d = evo.builder():set(world):spawn()
local e = evo.builder():set(world):spawn()
local query_a = evo.builder():set(world):include(a):spawn()
local query_b = evo.builder():set(world):include(b):spawn()
local query_c = evo.builder():set(world):include(c):spawn()
local query_d = evo.builder():set(world):include(d):spawn()
local query_e = evo.builder():set(world):include(e):spawn()
evo.multi_spawn_nr(N, { [world] = true, [a] = 0, [b] = 0, [c] = 0, [d] = 0, [e] = 0 })
evo.builder()
:set(world):group(world):query(query_a)
:execute(function(chunk, _, entity_count)
local as = chunk:components(a)
for i = 1, entity_count do as[i] = as[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_b)
:execute(function(chunk, _, entity_count)
local bs = chunk:components(b)
for i = 1, entity_count do bs[i] = bs[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_c)
:execute(function(chunk, _, entity_count)
local cs = chunk:components(c)
for i = 1, entity_count do cs[i] = cs[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_d)
:execute(function(chunk, _, entity_count)
local ds = chunk:components(d)
for i = 1, entity_count do ds[i] = ds[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_e)
:execute(function(chunk, _, entity_count)
local es = chunk:components(e)
for i = 1, entity_count do es[i] = es[i] * 2 end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Common Benchmarks: Tiny Fragmented Iteration | %d entities', N),
function(world)
world:update()
end, function()
local world = tiny.world()
---@type string[]
local chars = {}
for i = 1, 26 do
chars[i] = string.char(string.byte('a') + i - 1)
end
for i, char in ipairs(chars) do
for _ = 1, N do
world:addEntity({ [char] = i, data = i })
end
end
local Data = tiny.processingSystem()
Data.filter = tiny.requireAll('data')
Data.process = function(_, e) e.data = e.data * 2 end
local Last = tiny.processingSystem()
Last.filter = tiny.requireAll('z')
Last.process = function(_, e) e.z = e.z * 2 end
world:addSystem(Data)
world:addSystem(Last)
world:refresh()
return world
end)
basics.describe_bench(string.format('Common Benchmarks: Evolved Fragmented Iteration | %d entities', N),
function(world)
evo.process(world)
end, function()
local world = evo.builder()
:destruction_policy(evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local data = evo.spawn { [world] = true }
local chars = evo.multi_spawn(26, { [world] = true })
local query_data = evo.builder():set(world):include(data):spawn()
local query_z = evo.builder():set(world):include(chars[#chars]):spawn()
for i = 1, #chars do
evo.multi_spawn_nr(N, { [world] = true, [chars[i]] = i, [data] = i })
end
evo.builder()
:set(world):group(world):query(query_data)
:execute(function(chunk, _, entity_count)
local datas = chunk:components(data)
for i = 1, entity_count do datas[i] = datas[i] * 2 end
end):spawn()
evo.builder()
:set(world):group(world):query(query_z)
:execute(function(chunk, _, entity_count)
local zs = chunk:components(chars[#chars])
for i = 1, entity_count do zs[i] = zs[i] * 2 end
end):spawn()
return world
end, function(world)
evo.destroy(world)
end)

View File

@@ -0,0 +1,56 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N do
tables[i] = id()
end
for i = 1, N do
destroy(tables[i])
end
end, function()
return {}
end)
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d double ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N, 2 do
tables[i], tables[i + 1] = id(2)
end
for i = 1, N, 2 do
destroy(tables[i], tables[i + 1])
end
end, function()
return {}
end)
basics.describe_bench(string.format('Destroy Benchmarks: Acquire and Release %d triple ids', N),
function(tables)
local id = evo.id
local destroy = evo.destroy
for i = 1, N, 3 do
tables[i], tables[i + 1], tables[i + 2] = id(3)
end
for i = 1, N, 3 do
destroy(tables[i], tables[i + 1], tables[i + 2])
end
end, function()
return {}
end)

View File

@@ -0,0 +1,104 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 1 component', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
end
evo.commit()
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 3 components', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
end
evo.commit()
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Defer Set | %d entities with 5 components', N),
function()
local id, set = evo.id, evo.set
evo.defer()
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
end
evo.commit()
evo.batch_destroy(Q1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 1 component', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 3 components', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Migration Benchmarks: Simple Set | %d entities with 5 components', N),
function()
local id, set = evo.id, evo.set
for _ = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
end
evo.batch_destroy(Q1)
end)

View File

@@ -1,59 +0,0 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
function()
local clone = evo.clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
end)

View File

@@ -1,59 +0,0 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)
basics.describe_bench(string.format('Multi Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
end)

View File

@@ -0,0 +1,102 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 10000
print '----------------------------------------'
basics.describe_bench(string.format('Process Benchmarks: Evolved AoS Processing | %d entities', N),
function(w)
evo.process(w)
end,
function()
local wf = evo.builder()
:set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local pf = evo.builder():set(wf):spawn()
local vf = evo.builder():set(wf):spawn()
evo.multi_spawn_nr(N, {
[wf] = true,
[pf] = { x = 0, y = 0, z = 0, w = 0 },
[vf] = { x = 0, y = 0, z = 0, w = 0 },
})
evo.builder()
:set(wf)
:set(evo.GROUP, wf)
:set(evo.QUERY, evo.builder():set(wf):include(pf, vf):spawn())
:set(evo.EXECUTE, function(chunk, _, entity_count)
local ps, vs = chunk:components(pf, vf)
for i = 1, entity_count do
local p, s = ps[i], vs[i]
p.x = p.x + s.x
p.y = p.y + s.y
end
end)
:spawn()
return wf
end,
function(w)
evo.destroy(w)
end)
basics.describe_bench(string.format('Process Benchmarks: Evolved SoA Processing | %d entities', N),
function(w)
evo.process(w)
end,
function()
local wf = evo.builder()
:set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
:spawn()
local pxf = evo.builder():set(wf):spawn()
local pyf = evo.builder():set(wf):spawn()
local pzf = evo.builder():set(wf):spawn()
local pwf = evo.builder():set(wf):spawn()
local vxf = evo.builder():set(wf):spawn()
local vyf = evo.builder():set(wf):spawn()
local vzf = evo.builder():set(wf):spawn()
local vwf = evo.builder():set(wf):spawn()
evo.multi_spawn_nr(N, {
[wf] = true,
[pxf] = 0,
[pyf] = 0,
[pzf] = 0,
[pwf] = 0,
[vxf] = 0,
[vyf] = 0,
[vzf] = 0,
[vwf] = 0,
})
evo.builder()
:set(wf)
:set(evo.GROUP, wf)
:set(evo.QUERY, evo.builder():set(wf):include(pxf, pyf, vxf, vyf):spawn())
:set(evo.EXECUTE, function(chunk, _, entity_count)
local pxs, pys = chunk:components(pxf, pyf)
local vxs, vys = chunk:components(vxf, vyf)
for i = 1, entity_count do
pxs[i] = pxs[i] + vxs[i]
pys[i] = pys[i] + vys[i]
end
end)
:spawn()
return wf
end,
function(w)
evo.destroy(w)
end)

View File

@@ -0,0 +1,764 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
local D1, D2, D3, D4, D5 = evo.id(5)
evo.set(D1, evo.DEFAULT, true)
evo.set(D2, evo.DEFAULT, true)
evo.set(D3, evo.DEFAULT, true)
evo.set(D4, evo.DEFAULT, true)
evo.set(D5, evo.DEFAULT, true)
evo.set(D1, evo.DUPLICATE, function(v) return not v end)
evo.set(D2, evo.DUPLICATE, function(v) return not v end)
evo.set(D3, evo.DUPLICATE, function(v) return not v end)
evo.set(D4, evo.DUPLICATE, function(v) return not v end)
evo.set(D5, evo.DUPLICATE, function(v) return not v end)
local QF1 = evo.builder():include(F1):spawn()
local QD1 = evo.builder():include(D1):spawn()
local RF1 = evo.builder():require(F1):spawn()
local RF123 = evo.builder():require(F1, F2, F3):spawn()
local RF12345 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
local RD1 = evo.builder():require(D1):spawn()
local RD123 = evo.builder():require(D1, D2, D3):spawn()
local RD12345 = evo.builder():require(D1, D2, D3, D4, D5):spawn()
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [F1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 component', N),
function()
local spawn = evo.spawn
local components = { [D1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 components', N),
function()
local spawn = evo.spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [RF1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [RF1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [RD1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RF123] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 3 required components', N),
function()
local spawn = evo.spawn
local components = { [RD123] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RF12345] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn With Defaults | %d entities with 5 required components', N),
function()
local spawn = evo.spawn
local components = { [RD12345] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 component', N),
function()
local builder = evo.builder():set(D1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 components', N),
function()
local builder = evo.builder():set(F1):set(F2):set(F3):set(F4):set(F5)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 components', N),
function()
local builder = evo.builder():set(D1):set(D2):set(D3):set(D4):set(D5)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(RF1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(RF1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(RD1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RF123)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 3 required components', N),
function()
local builder = evo.builder():set(RD123)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RF12345)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 5 required components', N),
function()
local builder = evo.builder():set(RD12345)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [D1] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true, [F2] = true, [F3] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [D1] = true, [D2] = true, [D3] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [F1] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 required component', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [D1] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RF123] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RF123] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 3 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RD123] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RF12345] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RF12345] = true }
evo.defer()
multi_spawn_nr(N, components)
evo.commit()
evo.batch_destroy(QF1)
end)
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 5 required components', N),
function()
local multi_spawn_nr = evo.multi_spawn_nr
local components = { [RD12345] = true }
multi_spawn_nr(N, components)
evo.batch_destroy(QD1)
end)

View File

@@ -0,0 +1,136 @@
local evo = require 'evolved'
local basics = require 'develop.basics'
evo.debug_mode(false)
local N = 1000
local F1, F2, F3, F4, F5 = evo.id(5)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables', N),
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate and Collect %d tables', N),
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
for i = 1, N do
tables[i] = nil
end
collectgarbage('collect')
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 1 component / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 3 components / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 5 components / AoS', N),
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
e[F5] = true
tables[i] = e
end
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 1 component / SoA', N),
function(tables)
local fs1 = {}
for i = 1, N do
local e = {}
fs1[i] = true
tables[i] = e
end
tables[F1] = fs1
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 3 components / SoA', N),
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
end, function()
return {}
end)
basics.describe_bench(string.format('Table Benchmarks: Allocate %d tables with 5 components / SoA', N),
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
local fs5 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
fs4[i] = true
fs5[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
tables[F5] = fs5
end, function()
return {}
end)

View File

@@ -118,11 +118,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -124,11 +124,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -0,0 +1,308 @@
local evo = require 'evolved'
evo.debug_mode(true)
---
---
---
---
---
local __table_unpack = (function()
---@diagnostic disable-next-line: deprecated
return table.unpack or unpack
end)()
---
---
---
---
---
local all_fragment_list = {} ---@type evolved.fragment[]
for i = 1, math.random(1, 10) do
local fragment = evo.id()
all_fragment_list[i] = fragment
end
---@param query evolved.query
local function generate_query(query)
local include_set = {}
local include_list = {}
local include_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local include = all_fragment_list[math.random(1, #all_fragment_list)]
if not include_set[include] then
include_count = include_count + 1
include_set[include] = include_count
include_list[include_count] = include
end
end
local exclude_set = {}
local exclude_list = {}
local exclude_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local exclude = all_fragment_list[math.random(1, #all_fragment_list)]
if not exclude_set[exclude] then
exclude_count = exclude_count + 1
exclude_set[exclude] = exclude_count
exclude_list[exclude_count] = exclude
end
end
local variant_set = {}
local variant_list = {}
local variant_count = 0
for _ = 1, math.random(0, #all_fragment_list) do
local variant = all_fragment_list[math.random(1, #all_fragment_list)]
if not variant_set[variant] then
variant_count = variant_count + 1
variant_set[variant] = variant_count
variant_list[variant_count] = variant
end
end
if include_count > 0 then
evo.set(query, evo.INCLUDES, include_list)
end
if exclude_count > 0 then
evo.set(query, evo.EXCLUDES, exclude_list)
end
if variant_count > 0 then
evo.set(query, evo.VARIANTS, variant_list)
end
end
---@param query_count integer
---@return evolved.query[] query_list
---@return integer query_count
---@nodiscard
local function generate_queries(query_count)
local query_list = {} ---@type evolved.query[]
for i = 1, query_count do
local query = evo.id()
query_list[i] = query
generate_query(query)
end
return query_list, query_count
end
---@param entity evolved.entity
local function generate_entity(entity)
for _ = 0, math.random(0, #all_fragment_list) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(entity, fragment)
end
end
---@param entity_count integer
---@return evolved.entity[] entity_list
---@return integer entity_count
local function generate_entities(entity_count)
local entity_list = {} ---@type evolved.entity[]
for i = 1, entity_count do
local entity = evo.id()
entity_list[i] = entity
generate_entity(entity)
end
return entity_list, entity_count
end
local pre_query_list, pre_query_count = generate_queries(math.random(1, 10))
local pre_entity_list, pre_entity_count = generate_entities(math.random(1, 10))
for _ = 1, math.random(1, 5) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(fragment, evo.EXPLICIT)
end
for _ = 1, math.random(1, 5) do
local query = pre_query_list[math.random(1, pre_query_count)]
if math.random(1, 2) == 1 then
generate_query(query)
else
if math.random(1, 2) == 1 then
evo.remove(query, evo.INCLUDES)
else
evo.remove(query, evo.EXCLUDES)
end
end
end
local post_query_list, post_query_count = generate_queries(math.random(1, 10))
local post_entity_list, post_entity_count = generate_entities(math.random(1, 10))
---
---
---
---
---
local all_query_list = {}
local all_query_count = 0
local all_entity_list = {}
local all_entity_count = 0
for i = 1, pre_query_count do
all_query_count = all_query_count + 1
all_query_list[all_query_count] = pre_query_list[i]
end
for i = 1, post_query_count do
all_query_count = all_query_count + 1
all_query_list[all_query_count] = post_query_list[i]
end
for i = 1, pre_entity_count do
all_entity_count = all_entity_count + 1
all_entity_list[all_entity_count] = pre_entity_list[i]
end
for i = 1, post_entity_count do
all_entity_count = all_entity_count + 1
all_entity_list[all_entity_count] = post_entity_list[i]
end
---
---
---
---
---
local function execute_query(query)
local query_chunk_set = {}
local query_entity_set = {}
local query_include_list = evo.get(query, evo.INCLUDES) or {}
local query_exclude_list = evo.get(query, evo.EXCLUDES) or {}
local query_variant_list = evo.get(query, evo.VARIANTS) or {}
local query_include_count = #query_include_list
local query_exclude_count = #query_exclude_list
local query_variant_count = #query_variant_list
local query_include_set = {}
for _, include in ipairs(query_include_list) do
query_include_set[include] = true
end
local query_variant_set = {}
for _, variant in ipairs(query_variant_list) do
query_variant_set[variant] = true
end
for chunk, entity_list, entity_count in evo.execute(query) do
assert(not query_chunk_set[chunk])
query_chunk_set[chunk] = true
for i = 1, entity_count do
local entity = entity_list[i]
assert(not query_entity_set[entity])
query_entity_set[entity] = true
end
if query_include_count > 0 then
assert(chunk:has_all(__table_unpack(query_include_list)))
end
if query_exclude_count > 0 then
assert(not chunk:has_any(__table_unpack(query_exclude_list)))
end
if query_variant_count > 0 then
assert(chunk:has_any(__table_unpack(query_variant_list)))
end
end
for i = 1, all_entity_count do
local entity = all_entity_list[i]
local is_entity_matched =
(query_variant_count == 0 or evo.has_any(entity, __table_unpack(query_variant_list))) and
(query_include_count == 0 or evo.has_all(entity, __table_unpack(query_include_list))) and
(query_exclude_count == 0 or not evo.has_any(entity, __table_unpack(query_exclude_list)))
for fragment in evo.each(entity) do
if evo.has(fragment, evo.EXPLICIT) and not query_variant_set[fragment] and not query_include_set[fragment] then
is_entity_matched = false
end
end
if is_entity_matched then
assert(query_entity_set[entity])
else
assert(not query_entity_set[entity])
end
end
end
for i = 1, all_query_count do
execute_query(all_query_list[i])
end
---
---
---
---
---
for _ = 1, math.random(1, 5) do
local fragment = all_fragment_list[math.random(1, #all_fragment_list)]
evo.set(fragment, evo.EXPLICIT)
end
for _ = 1, math.random(1, 5) do
local query = pre_query_list[math.random(1, pre_query_count)]
if math.random(1, 2) == 1 then
generate_query(query)
else
local r = math.random(1, 3)
if r == 1 then
evo.remove(query, evo.INCLUDES)
elseif r == 2 then
evo.remove(query, evo.EXCLUDES)
else
evo.remove(query, evo.VARIANTS)
end
end
end
for i = 1, all_query_count do
execute_query(all_query_list[i])
end
---
---
---
---
---
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_query_list))
evo.destroy(__table_unpack(all_entity_list))
evo.destroy(__table_unpack(all_fragment_list))
if math.random(1, 2) == 1 then
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -78,11 +78,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -115,17 +115,17 @@ end
if math.random(1, 2) == 1 then
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_fragment_list))
else
evo.destroy(__table_unpack(all_fragment_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_entity_list))
end
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -64,11 +64,11 @@ end
---
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end
evo.destroy(__table_unpack(all_entity_list))
if math.random(1, 2) == 1 then
evo.collect_garbage()
evo.collect_garbage(math.random(1, 2) == 1)
end

View File

@@ -1,129 +0,0 @@
---@diagnostic disable: unused-local
local evo = require 'evolved'
evo.debug_mode(true)
---@class evolved.vector2
---@field x number
---@field y number
---@param x number
---@param y number
---@return evolved.vector2
---@nodiscard
local function vector2(x, y)
---@type evolved.vector2
return { x = x, y = y }
end
local consts = {
delta_time = 0.016,
physics_gravity = vector2(0, 9.81),
}
local groups = {
awake = evo.spawn(),
physics = evo.spawn(),
graphics = evo.spawn(),
shutdown = evo.spawn(),
}
local fragments = {
force = evo.spawn(),
position = evo.spawn(),
velocity = evo.spawn(),
}
local queries = {
physics_bodies = evo.builder()
:include(fragments.force, fragments.position, fragments.velocity)
:spawn(),
}
local awake_system = evo.builder()
:group(groups.awake)
:prologue(function()
print '-= | Awake | =-'
evo.builder()
:set(fragments.force, vector2(0, 0))
:set(fragments.position, vector2(0, 0))
:set(fragments.velocity, vector2(0, 0))
:spawn()
end):spawn()
local integrate_forces_system = evo.builder()
:group(groups.physics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
local delta_time, physics_gravity =
consts.delta_time, consts.physics_gravity
---@type evolved.vector2[], evolved.vector2[]
local forces, velocities = chunk:components(
fragments.force, fragments.velocity)
for i = 1, entity_count do
local force, velocity = forces[i], velocities[i]
velocity.x = velocity.x + (physics_gravity.x + force.x) * delta_time
velocity.y = velocity.y + (physics_gravity.y + force.y) * delta_time
end
end):spawn()
local integrate_velocities_system = evo.builder()
:group(groups.physics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
local delta_time =
consts.delta_time
---@type evolved.vector2[], evolved.vector2[], evolved.vector2[]
local forces, positions, velocities = chunk:components(
fragments.force, fragments.position, fragments.velocity)
for i = 1, entity_count do
local force, position, velocity = forces[i], positions[i], velocities[i]
position.x = position.x + velocity.x * delta_time
position.y = position.y + velocity.y * delta_time
force.x = 0
force.y = 0
end
end):spawn()
local graphics_system = evo.builder()
:group(groups.graphics)
:query(queries.physics_bodies)
:execute(function(chunk, entities, entity_count)
---@type evolved.vector2[]
local positions = chunk:components(
fragments.position)
for i = 1, entity_count do
local entity, position = entities[i], positions[i]
print(string.format(
'|-> {entity %d} at {%.4f, %.4f}',
entity, position.x, position.y))
end
end):spawn()
local shutdown_system = evo.builder()
:group(groups.shutdown)
:epilogue(function()
print '-= | Shutdown | =-'
evo.batch_destroy(queries.physics_bodies)
end):spawn()
do
evo.process(groups.awake)
for _ = 1, 10 do
evo.process(groups.physics)
evo.process(groups.graphics)
end
evo.process(groups.shutdown)
end

View File

@@ -0,0 +1,43 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
do
local e = evo.builder():set(f1, 42):set(f2, 'hello'):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
do
local p = evo.builder():set(f1, 42):build()
local e = evo.builder():set(f2, 'hello'):build(p)
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
do
local entity_list, entity_count = evo.builder():set(f1, 42):set(f2, 'hello'):multi_build(5)
assert(entity_count == 5)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
end
do
local p = evo.builder():set(f1, 42):build()
local entity_list, entity_count = evo.builder():set(f2, 'hello'):multi_build(5, p)
assert(entity_count == 5)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
end
end
end

View File

@@ -0,0 +1,107 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
assert(evo.defer())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.cancel())
end
do
assert(evo.defer())
assert(not evo.defer())
assert(not evo.cancel())
assert(not evo.defer())
assert(not evo.cancel())
assert(evo.commit())
end
do
local e, f = evo.id(2)
assert(evo.defer())
do
evo.set(e, f)
assert(not evo.has(e, f))
end
assert(evo.cancel())
assert(not evo.has(e, f))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.commit())
assert(evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.cancel())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local e, f1, f2 = evo.id(3)
assert(evo.defer())
do
evo.set(e, f1)
assert(not evo.has(e, f1))
assert(not evo.defer())
do
evo.set(e, f2)
assert(not evo.has(e, f2))
end
assert(not evo.commit())
end
assert(evo.cancel())
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end

View File

@@ -0,0 +1,561 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
do
local p = evo.spawn()
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn()
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f2, evo.DEFAULT, 42)
local p = evo.spawn()
local e = evo.clone(p, { [f1] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2))
assert(evo.has(e, f1) and evo.get(e, f1) == 'hello')
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f3] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 100)
assert(evo.has(e, f3) and evo.get(e, f3) == 10)
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == 'hello')
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local e = evo.clone(p, { [f1] = 'world', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 'world')
assert(evo.has(e, f2) and evo.get(e, f2) == 10)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(evo.has(e, f4) and evo.get(e, f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p)
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, {})
assert(evo.alive(e) and evo.empty(e))
end
do
local p = evo.spawn { [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f4))
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f4] = 'another' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f2, f4))
assert(evo.has(e, f2) and evo.get(e, f2) == 200 * 2)
assert(evo.has(e, f4) and evo.get(e, f4) == 'another')
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local e = evo.clone(p, { [f1] = 'hello', [f2] = 10 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == nil)
assert(evo.has(e, f2) and evo.get(e, f2) == 10 * 2)
assert(evo.has(e, f3) and evo.get(e, f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p)
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, { [f4] = 'another' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f3] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 100)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 10)
end
end
end
do
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == 'hello')
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DEFAULT, 42)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.TAG)
do
local p = evo.spawn { [f2] = 21, [f3] = 'hello', [f4] = true }
local es, ec = evo.multi_clone(2, p, { [f1] = 'world', [f2] = 10 })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 'world')
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == nil)
end
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.TAG)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 42)
evo.set(f2, evo.DUPLICATE, function(v) return v * 2 end)
evo.set(f3, evo.DUPLICATE, function() return nil end)
evo.set(f4, evo.UNIQUE)
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p)
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(3, p, {})
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local p = evo.spawn { [f4] = 'unique' }
local es, ec = evo.multi_clone(2, p, { [f4] = 'another' })
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f4))
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(4, p, { [f4] = 'another' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2, f4))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 200 * 2)
assert(evo.has(es[i], f4) and evo.get(es[i], f4) == 'another')
end
end
do
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(5, p, { [f1] = 'hello', [f2] = 10 })
assert(#es == 5 and ec == 5)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
local f1_set_count, f1_inserted_count = 0, 0
local f2_set_sum, f3_inserted_count = 0, 0
evo.set(f1, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f1_set_count = f1_set_count + 1
end)
evo.set(f1, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f1_inserted_count = f1_inserted_count + 1
end)
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(evo.get(e, f) == c)
f2_set_sum = f2_set_sum + c
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(evo.get(e, f) == c)
f3_inserted_count = f3_inserted_count + 1
end)
do
f1_set_count, f1_inserted_count = 0, 0
f2_set_sum, f3_inserted_count = 0, 0
local p = evo.spawn { [f2] = 100, [f4] = 'unique' }
local es, ec = evo.multi_clone(1, p, { [f1] = 'hello', [f2] = 10 })
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 10 * 2)
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
assert(f1_set_count == 1)
assert(f1_inserted_count == 1)
assert(f2_set_sum == 100 * 2 + 10 * 2)
assert(f3_inserted_count == 1)
end
end
end
do
local f1, f2 = evo.id(2)
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
local entity_list, entity_count = {}, 2
evo.multi_clone_to(entity_list, 1, entity_count, p)
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == 'hello')
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.multi_clone_to(entity_list, 2, entity_count, p)
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_clone_to(entity_list, 1, entity_count, p)
assert(entity_list[1] and entity_list[2])
assert(evo.empty_all(entity_list[1], entity_list[2]))
evo.commit()
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == 'hello')
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_clone_to(entity_list, 2, entity_count, p)
assert(entity_list[2] and entity_list[3])
assert(evo.empty_all(entity_list[2], entity_list[3]))
evo.commit()
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == 'hello')
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == 'hello')
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):build()
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
assert(select('#', evo.multi_clone_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 3)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
assert(select('#', b:multi_clone_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 5)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
assert(select('#', b:multi_build_nr(2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 7)
end
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):build()
local p = evo.spawn { [f1] = 42, [f2] = 'hello' }
do
local entity_list = {}
assert(select('#', evo.multi_clone_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 3)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
local entity_list = {}
assert(select('#', b:multi_clone_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 5)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, 'hello')
local entity_list = {}
assert(select('#', b:multi_build_to(entity_list, 1, 2, p)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 7)
end
end
end

View File

@@ -0,0 +1,67 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
assert(evo.depth() == 0)
assert(evo.defer())
assert(evo.depth() == 1)
assert(not evo.defer())
assert(evo.depth() == 2)
assert(not evo.cancel())
assert(evo.depth() == 1)
assert(evo.cancel())
assert(evo.depth() == 0)
end
do
assert(evo.depth() == 0)
assert(evo.defer())
assert(evo.depth() == 1)
assert(not evo.defer())
assert(evo.depth() == 2)
assert(not evo.commit())
assert(evo.depth() == 1)
assert(evo.commit())
assert(evo.depth() == 0)
end
do
assert(evo.depth() == 0)
assert(evo.defer())
assert(evo.depth() == 1)
assert(not evo.defer())
assert(evo.depth() == 2)
assert(not evo.cancel())
assert(evo.depth() == 1)
assert(evo.commit())
assert(evo.depth() == 0)
end
do
assert(evo.depth() == 0)
assert(evo.defer())
assert(evo.depth() == 1)
assert(not evo.defer())
assert(evo.depth() == 2)
assert(not evo.commit())
assert(evo.depth() == 1)
assert(evo.cancel())
assert(evo.depth() == 0)
end

View File

@@ -0,0 +1,106 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e = evo.id()
assert(evo.alive(e))
evo.destroy(e)
assert(not evo.alive(e))
evo.destroy(e)
assert(not evo.alive(e))
end
do
local e1, e2 = evo.id(2)
assert(evo.alive_all(e1, e2))
evo.destroy(e1, e2)
assert(not evo.alive_any(e1, e2))
evo.destroy(e1, e2)
assert(not evo.alive_any(e1, e2))
end
do
do
local e, f1, f2, f3 = evo.id(4)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(evo.alive(e) and not evo.has_any(e, f1, f2) and evo.has(e, f3))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f1, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(evo.alive(e) and not evo.has_any(e, f1, f2) and evo.has(e, f3))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f2, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(evo.alive(e) and not evo.has_any(e, f1, f2) and evo.has(e, f3))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f1, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT)
evo.set(f2, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_REMOVE_FRAGMENT)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(evo.alive(e) and not evo.has_any(e, f1, f2) and evo.has(e, f3))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f1, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(not evo.alive(e))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f2, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(not evo.alive(e))
end
do
local e, f1, f2, f3 = evo.id(4)
evo.set(f1, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
evo.set(f2, evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY)
evo.set(e, f1, 42)
evo.set(e, f2, 21)
evo.set(e, f3, 84)
evo.destroy(f1, f2)
assert(not evo.alive(e))
end
end

View File

@@ -0,0 +1,50 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e1, e2, f1, f2 = evo.id(4)
do
local chunk, place = evo.locate(e1)
assert(chunk == nil and place == 0)
end
evo.set(e1, f1, 42)
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1) and place == 1)
assert(chunk:components(f1)[place] == 42)
chunk, place = evo.locate(e2)
assert(chunk == nil and place == 0)
end
evo.set(e1, f2, 'hello')
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 1)
assert(chunk:components(f1)[place] == 42)
assert(chunk:components(f2)[place] == 'hello')
chunk, place = evo.locate(e2)
assert(chunk == nil and place == 0)
end
evo.set(e2, f1, 84)
evo.set(e2, f2, 'world')
do
local chunk, place = evo.locate(e1)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 1)
assert(chunk:components(f1)[place] == 42)
assert(chunk:components(f2)[place] == 'hello')
chunk, place = evo.locate(e2)
assert(chunk and chunk == evo.chunk(f1, f2) and place == 2)
assert(chunk:components(f1)[place] == 84)
assert(chunk:components(f2)[place] == 'world')
end
end

View File

@@ -0,0 +1,195 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local e1, e2, e3 = evo.id(3)
do
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e1, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
evo.set(e2, evo.NAME, 'lookup_hello')
evo.set(e3, evo.NAME, 'lookup_hello')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == nil)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
end
evo.set(e2, evo.NAME, 'lookup_world')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e3)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e2)
end
end
evo.set(e3, evo.NAME, 'lookup_world')
do
assert(evo.lookup('lookup_hello') == e1)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
end
evo.remove(e1, evo.NAME)
do
assert(evo.lookup('lookup_hello') == nil)
assert(evo.lookup('lookup_world') == e2)
do
local entity_list, entity_count = evo.multi_lookup('lookup_hello')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
do
local entity_list, entity_count = evo.multi_lookup('lookup_world')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e2 or entity_list[1] == e3)
end
end
end
do
local e1, e2, e3 = evo.id(3)
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e1)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e1 and entity_list[2] == e2)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e1 and entity_list[2] == e2 and entity_list[3] == e3)
end
evo.clear(e1, e2, e3)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
evo.set(e3, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 1 and entity_count == 1)
assert(entity_list[1] == e3)
end
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 2 and entity_count == 2)
assert(entity_list[1] == e3 and entity_list[2] == e2)
end
evo.set(e1, evo.NAME, 'lookup_e')
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 3 and entity_count == 3)
assert(entity_list[1] == e3 and entity_list[2] == e2 and entity_list[3] == e1)
end
evo.destroy(e3, e2, e1)
do
local entity_list, entity_count = evo.multi_lookup('lookup_e')
assert(entity_list and #entity_list == 0 and entity_count == 0)
end
end
do
local e1, e2 = evo.id(2)
evo.set(e1, evo.NAME, 'lookup_e')
evo.set(e2, evo.NAME, 'lookup_e')
do
local entity_list = {}
local entity_count = evo.multi_lookup_to(entity_list, 1, 'lookup_e')
assert(entity_count == 2 and entity_list[1] == e1 and entity_list[2] == e2)
end
do
local entity_list = {}
local entity_count = evo.multi_lookup_to(entity_list, 2, 'lookup_e')
assert(entity_count == 2 and entity_list[2] == e1 and entity_list[3] == e2)
end
end

View File

@@ -1525,7 +1525,7 @@ do
do
last_set_entity = 0
evo.set(e, f1, 41)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and not evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1539,13 +1539,13 @@ do
do
last_set_entity = 0
evo.set(e, f1, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
last_set_entity = 0
evo.set(e, f2, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1559,13 +1559,13 @@ do
do
last_set_entity = 0
evo.set(e, f1, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2) and evo.has(e, f3))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil and evo.get(e, f3) == 43)
last_set_entity = 0
evo.set(e, f2, 42)
assert(last_set_entity == e)
assert(last_set_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2) and evo.has(e, f3))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil and evo.get(e, f3) == 43)
@@ -1610,7 +1610,7 @@ do
last_assign_entity = 0
evo.set(e, f1)
assert(last_assign_entity == e)
assert(last_assign_entity == 0)
assert(evo.has(e, f1) and not evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -1623,7 +1623,7 @@ do
last_assign_entity = 0
evo.set(e, f2, 44)
assert(last_assign_entity == e)
assert(last_assign_entity == 0)
assert(evo.has(e, f1) and evo.has(e, f2))
assert(evo.get(e, f1) == nil and evo.get(e, f2) == nil)
end
@@ -2302,27 +2302,66 @@ do
evo.set(e2, f2, 44)
do
local iter, state = evo.execute(q)
local chunk = iter(state)
assert(chunk and chunk ~= evo.chunk(f1))
local e1_count = 0
local e2_count = 0
for _, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
end
evo.set(q, evo.EXCLUDES, { f2 })
do
local iter, state = evo.execute(q)
local chunk = iter(state)
assert(chunk and chunk ~= evo.chunk(f1))
local e1_count = 0
local e2_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
assert(not chunk:has(f2))
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 0)
end
evo.set(q, evo.INCLUDES, { f1 })
do
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk == evo.chunk(f1))
assert(entity_list and entity_list[1] == e1)
assert(entity_count == 1)
local e1_count = 0
local e2_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
assert(chunk:has(f1))
assert(not chunk:has(f2))
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
elseif entity_list[i] == e2 then
e2_count = e2_count + 1
end
end
end
assert(e1_count == 1)
assert(e2_count == 0)
end
end
@@ -2530,7 +2569,7 @@ do
end)
:on_remove(function(e, f, c)
f2_remove_count = f2_remove_count + 1
assert(evo.get(e, f) == nil)
assert(evo.get(e, f) == c)
assert(evo.alive(f))
assert(c == 82)
end)
@@ -3321,7 +3360,7 @@ do
remove_count = remove_count + 1
assert(f == f1)
assert(c == 51)
assert(evo.get(e, f1) == nil)
assert(evo.get(e, f1) == c)
do
evo.remove(e, f2)
@@ -3348,7 +3387,7 @@ do
remove_count = remove_count + 1
assert(f == f2)
assert(c == 51)
assert(evo.get(e, f2) == nil)
assert(evo.get(e, f2) == c)
end)
end
@@ -3518,8 +3557,7 @@ do
assert(e == e1 or e == e2)
assert(f == f1)
assert(c == 51)
assert(evo.get(e1, f1) == nil)
assert(evo.get(e2, f1) == nil)
assert(evo.get(e, f) == c)
end)
do
@@ -6373,3 +6411,726 @@ do
assert(evo.get(e, f) ~= v2_default)
end
end
do
local f1, f2 = evo.id(2)
local prefab = evo.builder():prefab():set(f1, 11):set(f2, 22):spawn()
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
evo.set(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(not evo.has(entity, f2) and evo.get(entity, f2) == nil)
end
evo.remove(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
evo.set(f1, evo.UNIQUE)
evo.set(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.empty(entity))
end
evo.remove(f1, evo.UNIQUE)
evo.remove(f2, evo.UNIQUE)
do
local entity = evo.clone(prefab)
assert(evo.has(entity, f1) and evo.get(entity, f1) == 11)
assert(evo.has(entity, f2) and evo.get(entity, f2) == 22)
end
end
do
do
local f = evo.id()
local c = evo.chunk(f)
local b = evo.builder():set(f, 42)
evo.collect_garbage()
local e = b:spawn()
assert(evo.locate(e) ~= c)
assert(evo.locate(e) == evo.chunk(f))
end
do
local f = evo.id()
local c = evo.chunk(f)
local b = evo.builder():set(f, 42)
evo.collect_garbage()
local es = b:multi_spawn(5)
for i = 1, 5 do
assert(evo.locate(es[i]) ~= c)
assert(evo.locate(es[i]) == evo.chunk(f))
end
end
end
do
local ff, ft = evo.id(2)
local b = evo.builder():set(ff, false):set(ft, true)
assert(b:has_all() and not b:has_any())
assert(b:has(ff) and b:has(ft) and b:has_all(ff, ft) and b:has_any(ff, ft))
end
do
do
local f = evo.id()
local q = evo.builder():include(f):spawn()
local e = evo.builder():set(f, 42):spawn()
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local q = evo.builder():include(f):spawn()
local iter, state = evo.execute(q)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end
do
local f1, f2 = evo.id(2)
local q = evo.builder():exclude(f2):spawn()
local e = evo.builder():set(f1, 42):spawn()
local e_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e then
e_count = e_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
end
end
assert(e_count == 1)
end
do
local f1, f2, f3 = evo.id(3)
local q = evo.builder():exclude(f2):spawn()
local e1 = evo.builder():set(f1, 42):spawn()
local e2 = evo.builder():set(f1, 42):set(f3, 21):spawn()
local e1_count, e2_count = 0, 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
if entity_list[i] == e2 then
e2_count = e2_count + 1
assert(chunk == evo.chunk(f1, f3))
assert(chunk:components(f1)[1] == 42)
assert(chunk:components(f3)[1] == 21)
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
end
do
local f1, f2 = evo.id(2)
local e = evo.builder():set(f1, 42):spawn()
local q = evo.builder():exclude(f2):spawn()
local e_count = 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e then
e_count = e_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
end
end
assert(e_count == 1)
end
do
local f1, f2, f3 = evo.id(3)
local e1 = evo.builder():set(f1, 42):spawn()
local e2 = evo.builder():set(f1, 42):set(f3, 21):spawn()
local q = evo.builder():exclude(f2):spawn()
local e1_count, e2_count = 0, 0
for chunk, entity_list, entity_count in evo.execute(q) do
for i = 1, entity_count do
if entity_list[i] == e1 then
e1_count = e1_count + 1
assert(chunk == evo.chunk(f1))
assert(chunk:components(f1)[1] == 42)
end
if entity_list[i] == e2 then
e2_count = e2_count + 1
assert(chunk == evo.chunk(f1, f3))
assert(chunk:components(f1)[1] == 42)
assert(chunk:components(f3)[1] == 21)
end
end
end
assert(e1_count == 1)
assert(e2_count == 1)
end
end
do
local f1, f2 = evo.id(2)
local q1 = evo.builder():include(f1):spawn()
local q2 = evo.builder():include(f2):spawn()
local e12 = evo.builder():set(f1, 42):set(f2, 21):spawn()
do
local iter, state = evo.execute(q1)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
do
local iter, state = evo.execute(q2)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
evo.set(f1, evo.EXPLICIT)
do
local iter, state = evo.execute(q1)
local chunk, entity_list, entity_count = iter(state)
assert(chunk and entity_list and entity_count)
assert(chunk == evo.chunk(f1, f2) and entity_count == 1 and entity_list[1] == e12)
end
do
local iter, state = evo.execute(q2)
local chunk, entity_list, entity_count = iter(state)
assert(not chunk and not entity_list and not entity_count)
end
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2 = evo.id(2)
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
local e1 = evo.builder():set(f1, v2(10, 11)):spawn()
local e2 = evo.builder():set(f1, v2(12, 13)):set(f2, v2(14, 15)):spawn()
do
assert(evo.has(e1, f1) and evo.get(e1, f1).x == 10 and evo.get(e1, f1).y == 11)
assert(evo.get(e1, f1) ~= f1_default)
assert(evo.has(e2, f1) and evo.get(e2, f1).x == 12 and evo.get(e2, f1).y == 13)
assert(evo.get(e2, f1) ~= f1_default)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
evo.set(f1, evo.TAG)
do
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
evo.remove(f1, evo.TAG)
do
assert(evo.has(e1, f1) and evo.get(e1, f1).x == 1 and evo.get(e1, f1).y == 2)
assert(evo.get(e1, f1) ~= f1_default)
assert(evo.has(e2, f1) and evo.get(e2, f1).x == 1 and evo.get(e2, f1).y == 2)
assert(evo.get(e2, f1) ~= f1_default)
assert(evo.has(e2, f2) and evo.get(e2, f2).x == 14 and evo.get(e2, f2).y == 15)
assert(evo.get(e2, f2) ~= f2_default)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, false)
evo.set(f3, evo.TAG)
local v_set_sum = 0
local v_insert_sum = 0
local f3_set_times = 0
local f3_insert_times = 0
evo.set(f1, evo.ON_SET, function(e, f, v)
assert(f == f1)
v_set_sum = v_set_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f1, evo.ON_INSERT, function(e, f, v)
assert(f == f1)
v_insert_sum = v_insert_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f3, evo.ON_SET, function(e, f, v)
assert(f == f3)
f3_set_times = f3_set_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
evo.set(f3, evo.ON_INSERT, function(e, f, v)
assert(f == f3)
f3_insert_times = f3_insert_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
do
local e = evo.spawn({ [f1] = 42 })
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local e = evo.clone(entity_prefab)
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local e = evo.clone(entity_prefab, { [f1] = 21 })
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
assert(v_set_sum == 42 * 4 + 21 * 1)
assert(v_insert_sum == 42 * 4 + 21 * 1)
assert(f3_set_times == 5)
assert(f3_insert_times == 5)
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4, f5, f6, f7 = evo.id(7)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
evo.set(f5, evo.REQUIRES, { f6, f7 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
local f6_default = v2(14, 15)
local f7_default = v2(16, 17)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f6, evo.DEFAULT, f6_default)
evo.set(f7, evo.DEFAULT, f7_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
evo.set(f5, evo.DUPLICATE, v2_clone)
evo.set(f6, evo.DUPLICATE, v2_clone)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
local q_f1 = evo.builder():include(f1):spawn()
local f2_v = v2(20, 21)
evo.batch_set(q_f1, f2, f2_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
end
local f5_v = v2(30, 31)
evo.batch_set(q_f1, f5, f5_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 30 and evo.get(e, f5).y == 31)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
f5_v = v2(32, 33)
evo.batch_set(q_f1, f5, f5_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 32 and evo.get(e, f5).y == 33)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
end
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4, f5, f6, f7 = evo.id(7)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
evo.set(f5, evo.REQUIRES, { f6, f7 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
local f6_default = v2(14, 15)
local f7_default = v2(16, 17)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f6, evo.DEFAULT, f6_default)
evo.set(f7, evo.DEFAULT, f7_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
evo.set(f5, evo.DUPLICATE, v2_clone)
evo.set(f6, evo.DUPLICATE, v2_clone)
local f5_set_sum = 0
local f5_insert_sum = 0
local f6_set_sum = 0
local f6_insert_sum = 0
local f7_set_sum = 0
local f7_insert_sum = 0
evo.set(f5, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f5)
f5_set_sum = f5_set_sum + v.x + v.y
end)
evo.set(f5, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f5)
f5_insert_sum = f5_insert_sum + v.x + v.y
end)
evo.set(f6, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f6)
f6_set_sum = f6_set_sum + v.x + v.y
end)
evo.set(f6, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f6)
f6_insert_sum = f6_insert_sum + v.x + v.y
end)
evo.set(f7, evo.ON_SET, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f7)
f7_set_sum = f7_set_sum + v.x + v.y
end)
evo.set(f7, evo.ON_INSERT, function(e, f, v)
assert(evo.get(e, f) == v)
assert(f == f7)
f7_insert_sum = f7_insert_sum + v.x + v.y
end)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
local q_f1 = evo.builder():include(f1):spawn()
local f2_v = v2(20, 21)
evo.batch_set(q_f1, f2, f2_v)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
end
assert(f5_set_sum == 0)
assert(f5_insert_sum == 0)
assert(f6_set_sum == 0)
assert(f6_insert_sum == 0)
assert(f7_set_sum == 0)
assert(f7_insert_sum == 0)
local f5_v = v2(30, 31)
evo.batch_set(q_f1, f5, f5_v)
assert(f5_set_sum == (30 + 31) * entity_count)
assert(f5_insert_sum == (30 + 31) * entity_count)
assert(f6_set_sum == (14 + 15) * entity_count)
assert(f6_insert_sum == (14 + 15) * entity_count)
assert(f7_set_sum == (16 + 17) * entity_count)
assert(f7_insert_sum == (16 + 17) * entity_count)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 30 and evo.get(e, f5).y == 31)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
f5_set_sum = 0
f5_insert_sum = 0
f6_set_sum = 0
f6_insert_sum = 0
f7_set_sum = 0
f7_insert_sum = 0
f5_v = v2(32, 33)
evo.batch_set(q_f1, f5, f5_v)
assert(f5_set_sum == (32 + 33) * entity_count)
assert(f5_insert_sum == 0)
assert(f6_set_sum == 0)
assert(f6_insert_sum == 0)
assert(f7_set_sum == 0)
assert(f7_insert_sum == 0)
for i = 1, entity_count do
local e = entity_list[i]
assert(evo.has(e, f1) and evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2).x == 20 and evo.get(e, f2).y == 21)
assert(evo.has(e, f3) and evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4).x == 12 and evo.get(e, f4).y == 13)
assert(evo.has(e, f5) and evo.get(e, f5).x == 32 and evo.get(e, f5).y == 33)
assert(evo.has(e, f6) and evo.get(e, f6).x == 14 and evo.get(e, f6).y == 15)
assert(evo.has(e, f7) and evo.get(e, f7).x == 16 and evo.get(e, f7).y == 17)
assert(evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f2) ~= f2_v and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f4) == f4_default)
assert(evo.get(e, f5) ~= f5_v)
assert(evo.get(e, f6) ~= f6_default)
assert(evo.get(e, f7) == f7_default)
end
end
end
do
local s1, s2 = evo.id(2)
local process_order = ''
evo.set(s1, evo.PROLOGUE, function()
process_order = process_order .. '1'
end)
evo.set(s2, evo.PROLOGUE, function()
process_order = process_order .. '2'
end)
do
process_order = ''
evo.set(s2, evo.GROUP, s1)
evo.process(s1)
assert(process_order == '12')
end
do
process_order = ''
evo.remove(s2, evo.GROUP)
evo.process(s1)
assert(process_order == '1')
end
end
do
local s1, s2, s3 = evo.id(3)
local process_order = ''
evo.set(s1, evo.PROLOGUE, function()
process_order = process_order .. '1'
end)
evo.set(s2, evo.PROLOGUE, function()
process_order = process_order .. '2'
end)
evo.set(s3, evo.PROLOGUE, function()
process_order = process_order .. '3'
end)
do
process_order = ''
evo.set(s2, evo.GROUP, s1)
evo.process(s1)
assert(process_order == '12')
end
do
process_order = ''
evo.set(s2, evo.GROUP, s3)
evo.process(s1)
assert(process_order == '1')
evo.process(s3)
assert(process_order == '132')
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.NAME, 'f1')
evo.set(f2, evo.NAME, 'f2')
do
local c1 = evo.chunk(f1)
assert(tostring(c1) == '<f1>')
local c2 = evo.chunk(f2)
assert(tostring(c2) == '<f2>')
local c12 = evo.chunk(f1, f2)
assert(tostring(c12) == '<f1, f2>')
local c21 = evo.chunk(f2, f1)
assert(tostring(c21) == '<f1, f2>')
end
do
local b = evo.builder():set(f1)
assert(tostring(b) == '<f1>')
b:set(f1, 1):set(f2, 2)
assert(tostring(b) == '<f1, f2>')
end
end

View File

@@ -0,0 +1,244 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
local e1 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
local e2 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 11)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 22)
local e11 = evo.clone(e1, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 3
f2s[p] = f2s[p] * 4
end)
local e22 = evo.clone(e2, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 30
f2s[p] = f2s[p] + 40
end)
assert(evo.has(e11, f1) and evo.get(e11, f1) == 6)
assert(evo.has(e11, f2) and evo.get(e11, f2) == 24)
assert(evo.has(e22, f1) and evo.get(e22, f1) == 41)
assert(evo.has(e22, f2) and evo.get(e22, f2) == 62)
end
do
local f1, f2 = evo.id(2)
evo.defer()
local e1 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
local e2 = evo.spawn({ [f1] = 1, [f2] = 2 }, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(not evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(not evo.has(e1, f2) and evo.get(e1, f2) == nil)
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(not evo.has(e2, f2) and evo.get(e2, f2) == nil)
evo.commit()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 11)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 22)
evo.defer()
local e11 = evo.clone(e1, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 3
f2s[p] = f2s[p] * 4
end)
local e22 = evo.clone(e2, nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 30
f2s[p] = f2s[p] + 40
end)
assert(not evo.has(e11, f1) and evo.get(e11, f1) == nil)
assert(not evo.has(e11, f2) and evo.get(e11, f2) == nil)
assert(not evo.has(e22, f1) and evo.get(e22, f1) == nil)
assert(not evo.has(e22, f2) and evo.get(e22, f2) == nil)
evo.commit()
assert(evo.has(e11, f1) and evo.get(e11, f1) == 6)
assert(evo.has(e11, f2) and evo.get(e11, f2) == 24)
assert(evo.has(e22, f1) and evo.get(e22, f1) == 41)
assert(evo.has(e22, f2) and evo.get(e22, f2) == 62)
end
do
local f1, f2 = evo.id(2)
local es, ec = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 }, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
local es2, ec2 = evo.multi_clone(10, es[1], nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end
do
local f1, f2 = evo.id(2)
evo.defer()
local es, ec = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 }, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(not evo.has(e, f1) and evo.get(e, f1) == nil)
assert(not evo.has(e, f2) and evo.get(e, f2) == nil)
end
evo.commit()
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
evo.defer()
local es2, ec2 = evo.multi_clone(10, es[1], nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(not evo.has(e, f1) and evo.get(e, f1) == nil)
assert(not evo.has(e, f2) and evo.get(e, f2) == nil)
end
evo.commit()
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end
do
local f1, f2 = evo.id(2)
local e1 = evo.builder():set(f1, 1):set(f2, 2):build(nil, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 2)
assert(evo.has(e1, f2) and evo.get(e1, f2) == 6)
local e2 = evo.builder():build(e1, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 12)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 26)
local e3 = evo.builder():set(f2, 3):build(e1, function(c, p)
local f1s, f2s = c:components(f1, f2)
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 12)
assert(evo.has(e3, f2) and evo.get(e3, f2) == 23)
end
do
local f1, f2 = evo.id(2)
local es, ec = evo.builder():set(f1, 1):set(f2, 2):multi_build(10, nil, function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] * 2
f2s[p] = f2s[p] * 3
end
end)
for i = 1, ec do
local e = es[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 2)
assert(evo.has(e, f2) and evo.get(e, f2) == 6)
end
local es2, ec2 = evo.builder():multi_build(10, es[1], function(c, b, e)
local f1s, f2s = c:components(f1, f2)
for p = b, e do
f1s[p] = f1s[p] + 10
f2s[p] = f2s[p] + 20
end
end)
for i = 1, ec2 do
local e = es2[i]
assert(evo.has(e, f1) and evo.get(e, f1) == 12)
assert(evo.has(e, f2) and evo.get(e, f2) == 26)
end
end

View File

@@ -1,5 +1,7 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local entity_list
@@ -306,3 +308,463 @@ do
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f3, evo.TAG)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
evo.set(f2, evo.DEFAULT, false)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
assert(evo.has(e, f3) and evo.get(e, f3) == nil)
end
end
local v_set_sum = 0
local v_insert_sum = 0
local f3_set_times = 0
local f3_insert_times = 0
evo.set(f1, evo.ON_SET, function(e, f, v)
assert(f == f1)
v_set_sum = v_set_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f1, evo.ON_INSERT, function(e, f, v)
assert(f == f1)
v_insert_sum = v_insert_sum + v
assert(evo.get(e, f) == v)
end)
evo.set(f3, evo.ON_SET, function(e, f, v)
assert(f == f3)
f3_set_times = f3_set_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
evo.set(f3, evo.ON_INSERT, function(e, f, v)
assert(f == f3)
f3_insert_times = f3_insert_times + 1
assert(v == nil)
assert(evo.has(e, f))
end)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = 42 })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab)
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
do
local entity_prefab = evo.builder():set(f1, 42):spawn()
evo.remove(entity_prefab, f2, f3)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f1] = 21 })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == false)
end
end
assert(v_set_sum == 42 * 6 + 21 * 2)
assert(v_insert_sum == 42 * 6 + 21 * 2)
assert(f3_set_times == 8)
assert(f3_insert_times == 8)
end
do
local function v2(x, y) return { x = x or 0, y = y or 0 } end
local function v2_clone(v) return { x = v.x, y = v.y } end
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.REQUIRES, { f2, f3, f4 })
local f1_default = v2(1, 2)
local f2_default = v2(3, 4)
local f3_default = v2(10, 11)
local f4_default = v2(12, 13)
evo.set(f1, evo.DEFAULT, f1_default)
evo.set(f2, evo.DEFAULT, f2_default)
evo.set(f3, evo.DEFAULT, f3_default)
evo.set(f4, evo.DEFAULT, f4_default)
evo.set(f1, evo.DUPLICATE, v2_clone)
evo.set(f2, evo.DUPLICATE, v2_clone)
evo.set(f3, evo.DUPLICATE, v2_clone)
do
local entity_list, entity_count = evo.multi_spawn(2, { [f1] = v2(5, 6), [f2] = v2(7, 8) })
assert(entity_list and #entity_list == 2)
assert(entity_count == 2)
for i = 1, entity_count do
local e = entity_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default)
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default)
assert(evo.get(e, f2).x == 7 and evo.get(e, f2).y == 8)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
do
local entity_prefab = evo.builder():set(f1, v2(5, 6)):set(f2, v2(7, 8)):spawn()
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f2] = f2_default })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default and evo.get(e, f1) ~= evo.get(entity_prefab, f1))
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default and evo.get(e, f2) ~= evo.get(entity_prefab, f2))
assert(evo.get(e, f2).x == 3 and evo.get(e, f2).y == 4)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
do
local entity_prefab = evo.builder():set(f1, v2(5, 6)):set(f2, v2(7, 8)):spawn()
evo.remove(entity_prefab, f2, f3, f4)
local clone_list, clone_count = evo.multi_clone(2, entity_prefab, { [f2] = f2_default })
assert(clone_list and #clone_list == 2)
assert(clone_count == 2)
for i = 1, clone_count do
local e = clone_list[i]
assert(e and not evo.empty(e))
assert(evo.has(e, f1) and evo.get(e, f1) ~= f1_default and evo.get(e, f1) ~= evo.get(entity_prefab, f1))
assert(evo.get(e, f1).x == 5 and evo.get(e, f1).y == 6)
assert(evo.has(e, f2) and evo.get(e, f2) ~= f2_default and evo.get(e, f2) ~= evo.get(entity_prefab, f2))
assert(evo.get(e, f2).x == 3 and evo.get(e, f2).y == 4)
assert(evo.has(e, f3) and evo.get(e, f3) ~= f3_default)
assert(evo.get(e, f3).x == 10 and evo.get(e, f3).y == 11)
assert(evo.has(e, f4) and evo.get(e, f4) == f4_default)
end
end
end
do
local f1, f2 = evo.id(2)
do
local entity_list, entity_count = {}, 2
evo.multi_spawn_to(entity_list, 1, entity_count, { [f1] = 42, [f2] = "hello" })
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == "hello")
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.multi_spawn_to(entity_list, 2, entity_count, { [f1] = 42, [f2] = "hello" })
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_spawn_to(entity_list, 1, entity_count, { [f1] = 42, [f2] = "hello" })
assert(entity_list[1] and entity_list[2])
assert(evo.empty_all(entity_list[1], entity_list[2]))
evo.commit()
assert(evo.has_all(entity_list[1], f1, f2))
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.get(entity_list[1], f1) == 42 and evo.get(entity_list[1], f2) == "hello")
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
end
do
local entity_list, entity_count = {}, 2
evo.defer()
evo.multi_spawn_to(entity_list, 2, entity_count, { [f1] = 42, [f2] = "hello" })
assert(entity_list[2] and entity_list[3])
assert(evo.empty_all(entity_list[2], entity_list[3]))
evo.commit()
assert(evo.has_all(entity_list[2], f1, f2))
assert(evo.has_all(entity_list[3], f1, f2))
assert(evo.get(entity_list[2], f1) == 42 and evo.get(entity_list[2], f2) == "hello")
assert(evo.get(entity_list[3], f1) == 42 and evo.get(entity_list[3], f2) == "hello")
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):spawn()
do
assert(select('#', evo.multi_spawn_nr(2, { [f1] = 42, [f2] = "hello" })) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 2)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
assert(select('#', b:multi_spawn_nr(2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 4)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
assert(select('#', b:multi_build_nr(2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 6)
end
end
end
do
local f1, f2 = evo.id(2)
local q12 = evo.builder():include(f1, f2):spawn()
do
local entity_list = {}
assert(select('#', evo.multi_spawn_to(entity_list, 1, 2, { [f1] = 42, [f2] = "hello" })) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 2)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
local entity_list = {}
assert(select('#', b:multi_spawn_to(entity_list, 1, 2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 4)
end
end
do
local b = evo.builder():set(f1, 42):set(f2, "hello")
local entity_list = {}
assert(select('#', b:multi_build_to(entity_list, 1, 2)) == 0)
do
local entity_count = 0
for chunk in evo.execute(q12) do
local _, chunk_entity_count = chunk:entities()
entity_count = entity_count + chunk_entity_count
end
assert(entity_count == 6)
end
end
end

View File

@@ -1,5 +1,7 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local id = evo.id()

View File

@@ -0,0 +1,109 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == 11 and payload2 == 22 and payload3 == 33)
end)
:spawn()
evo.process_with(s, 11, 22, 33)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == 42 and payload3 == nil)
end)
:spawn()
evo.process_with(s, nil, 42)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local s = evo.builder()
:include(f)
:prologue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
end)
:execute(function(chunk, entity_list, entity_count, payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(payload1, payload2, payload3)
assert(payload1 == nil and payload2 == nil and payload3 == nil)
end)
:spawn()
evo.process_with(s)
end
do
local f = evo.id()
local e = evo.builder():set(f, 42):spawn()
local prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
local function sum(...)
local s = 0
for i = 1, select('#', ...) do
s = s + select(i, ...)
end
return s
end
local function iota(n)
if n == 0 then return end
return n, iota(n - 1)
end
local s = evo.builder()
:include(f)
:prologue(function(...)
prologue_sum = prologue_sum + sum(...)
end)
:execute(function(chunk, entity_list, entity_count, ...)
execute_sum = execute_sum + sum(...)
assert(chunk == evo.chunk(f) and entity_count == 1 and entity_list[1] == e)
end)
:epilogue(function(...)
epilogue_sum = epilogue_sum + sum(...)
end)
:spawn()
for n = 0, 50 do
prologue_sum, execute_sum, epilogue_sum = 0, 0, 0
evo.process_with(s, iota(n))
local expect_sum = (n * (n + 1)) / 2
assert(prologue_sum == expect_sum)
assert(execute_sum == expect_sum)
assert(epilogue_sum == expect_sum)
end
end

View File

@@ -0,0 +1,596 @@
local evo = require 'evolved'
evo.debug_mode(true)
---@type ffilib?
local ffi = (function()
if package and package.loaded then
local loaded_ffi = package.loaded.ffi
if loaded_ffi then return loaded_ffi end
end
if package and package.preload then
local ffi_loader = package.preload.ffi
if ffi_loader then return ffi_loader() end
end
end)()
if not ffi then
return
end
local FLOAT_TYPEOF = ffi.typeof('float')
local FLOAT_SIZEOF = ffi.sizeof(FLOAT_TYPEOF)
local FLOAT_STORAGE_TYPEOF = ffi.typeof('$[?]', FLOAT_TYPEOF)
local DOUBLE_TYPEOF = ffi.typeof('double')
local DOUBLE_SIZEOF = ffi.sizeof(DOUBLE_TYPEOF)
local DOUBLE_STORAGE_TYPEOF = ffi.typeof('$[?]', DOUBLE_TYPEOF)
local STORAGE_SIZES = {}
---@type evolved.realloc
local function float_realloc(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
STORAGE_SIZES[src] = nil
return
else
if src then
assert(src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
else
assert(src_size == 0)
end
local dst = ffi.new(FLOAT_STORAGE_TYPEOF, dst_size + 1)
STORAGE_SIZES[dst] = dst_size
if src then
ffi.copy(dst + 1, src + 1, math.min(src_size, dst_size) * FLOAT_SIZEOF)
end
return dst
end
end
---@type evolved.realloc
local function double_realloc(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
STORAGE_SIZES[src] = nil
return
else
if src then
assert(src_size > 0)
local expected_src_size = STORAGE_SIZES[src]
assert(expected_src_size == src_size)
else
assert(src_size == 0)
end
local dst = ffi.new(DOUBLE_STORAGE_TYPEOF, dst_size + 1)
STORAGE_SIZES[dst] = dst_size
if src then
ffi.copy(dst + 1, src + 1, math.min(src_size, dst_size) * DOUBLE_SIZEOF)
end
return dst
end
end
---@type evolved.compmove
local function double_compmove(src, f, e, t, dst)
ffi.copy(dst + t, src + f, (e - f + 1) * DOUBLE_SIZEOF)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local e1 = evo.builder():set(f1, 21):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
local e2 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
local e3 = evo.builder():set(f1, 84):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 84)
evo.destroy(e1)
assert(not evo.has(e1, f1))
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(evo.has(e3, f1) and evo.get(e3, f1) == 84)
evo.destroy(e3)
assert(not evo.has(e1, f1))
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(not evo.has(e3, f1))
evo.destroy(e2)
assert(not evo.has(e1, f1))
assert(not evo.has(e2, f1))
assert(not evo.has(e3, f1))
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local q1 = evo.builder():include(f1):build()
do
local es, ec = {}, 10
for i = 1, ec do es[i] = evo.spawn({ [f1] = i }) end
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == i) end
end
do
local p = evo.builder():set(f1, 42):build()
local es, ec = {}, 10
for i = 1, ec do es[i] = evo.clone(p) end
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42) end
end
do
local es1, ec1 = evo.multi_spawn(10, { [f1] = 42 })
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 42) end
local es2, ec2 = evo.multi_spawn(20, { [f1] = 84 })
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 42) end
for i = 1, ec2 do assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 84) end
end
do
local p = evo.builder():set(f1, 21):build()
local es1, ec1 = evo.multi_clone(10, p)
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 21) end
local es2, ec2 = evo.multi_clone(20, p)
for i = 1, ec1 do assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 21) end
for i = 1, ec2 do assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 21) end
end
evo.batch_destroy(q1)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local f2 = evo.builder():realloc(double_realloc):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local e = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
evo.remove(e, f1)
assert(not evo.has(e, f1))
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
end
do
local e = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e, f1) and evo.get(e, f1) == 21)
assert(evo.has(e, f2) and evo.get(e, f2) == 42)
evo.clear(e)
assert(not evo.has(e, f1))
assert(not evo.has(e, f2))
end
do
local es, ec = evo.multi_spawn(10, { [f1] = 21, [f2] = 42 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_remove(q1, f1)
local e12 = evo.builder():set(f1, 1):set(f2, 2):build()
assert(evo.has(e12, f1) and evo.get(e12, f1) == 1)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_set(q2, f1, 84)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 84)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 84)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
evo.batch_set(q2, f1, 21)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 21)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 42)
end
end
end
do
local f1 = evo.builder():realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es1, ec1 = evo.multi_spawn(10, { [f1] = 1, [f2] = 2 })
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 1)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
local es2, ec2 = evo.multi_spawn(20, { [f1] = 3, [f2] = 4 })
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 1)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 3)
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
local e2 = evo.builder():set(f2, 42):build()
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
evo.batch_remove(q1, f1)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
for i = 1, ec1 do
assert(not evo.has(es1[i], f1))
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(not evo.has(es2[i], f1))
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
local e12 = evo.builder():set(f1, 21):set(f2, 42):build()
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 21)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 42)
evo.batch_set(q2, f1, 84)
assert(evo.has(e2, f2) and evo.get(e2, f2) == 42)
assert(evo.has(e12, f1) and evo.get(e12, f1) == 84)
assert(evo.has(e12, f2) and evo.get(e12, f2) == 42)
for i = 1, ec1 do
assert(evo.has(es1[i], f1) and evo.get(es1[i], f1) == 84)
assert(evo.has(es1[i], f2) and evo.get(es1[i], f2) == 2)
end
for i = 1, ec2 do
assert(evo.has(es2[i], f1) and evo.get(es2[i], f1) == 84)
assert(evo.has(es2[i], f2) and evo.get(es2[i], f2) == 4)
end
end
end
do
local f1 = evo.builder():default(42):build()
local es, ec = evo.multi_spawn(10, { [f1] = 21 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 21) end
evo.set(f1, evo.TAG)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
evo.remove(f1, evo.TAG)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42) end
end
do
local f1 = evo.builder():realloc(float_realloc):build()
local e1 = evo.builder():set(f1, 3):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.set(f1, evo.REALLOC, double_realloc)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.remove(f1, evo.REALLOC)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
evo.set(f1, evo.REALLOC, double_realloc)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 3)
end
do
local f1 = evo.builder():realloc(double_realloc):build()
local es, ec = evo.multi_spawn(20, { [f1] = 42 })
for i = 1, ec / 2 do
evo.destroy(es[ec - i + 1])
end
evo.collect_garbage()
for i = 1, ec / 2 do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f2] = 2 })
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_remove(q1, f1)
for i = 1, ec do
assert(not evo.has(es[i], f1))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
do
evo.collect_garbage()
local f1 = evo.builder():name('f1'):realloc(double_realloc):compmove(double_compmove):build()
local f2 = evo.builder():name('f2'):realloc(double_realloc):compmove(double_compmove):build()
local q1 = evo.builder():include(f1):build()
local q2 = evo.builder():include(f2):build()
do
local es, ec = evo.multi_spawn(40, { [f1] = 1, [f2] = 2 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q2)
end
do
local es, ec = evo.multi_spawn(50, { [f1] = 1 })
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(not evo.has(es[i], f2))
end
evo.batch_set(q1, f2, 2)
for i = 1, ec do
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 1)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 2)
end
evo.batch_destroy(q1, q2)
end
do
evo.spawn({ [f1] = 1 })
evo.spawn({ [f2] = 2 })
evo.spawn({ [f1] = 1, [f2] = 2 })
end
evo.collect_garbage()
end
do
evo.collect_garbage()
local alloc_call_count = 0
local free_call_count = 0
local resize_call_count = 0
local function ctor_realloc()
---@type evolved.realloc
return function(src, src_size, dst_size)
if dst_size == 0 then
assert(src and src_size > 0)
free_call_count = free_call_count + 1
return
else
if src then
assert(src_size > 0)
resize_call_count = resize_call_count + 1
else
assert(src_size == 0)
alloc_call_count = alloc_call_count + 1
end
local dst = {}
if src then
for i = 1, math.min(src_size, dst_size) do
dst[i] = src[i]
end
end
return dst
end
end
end
do
local realloc1 = ctor_realloc()
local realloc2 = ctor_realloc()
local f1 = evo.builder():default(44):realloc(realloc1):build()
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 21):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(alloc_call_count == 1 and free_call_count == 0)
local e2 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 21)
assert(evo.has(e2, f1) and evo.get(e2, f1) == 42)
assert(alloc_call_count == 1 and free_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e1)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e2)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local es, ec = evo.multi_spawn(10, { [f1] = 84 })
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
for i = 1, ec / 2 do evo.destroy(es[i]) end
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 1)
evo.set(f1, evo.REALLOC, realloc2)
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 1)
for i = 1, ec do evo.destroy(es[i]) end
evo.collect_garbage()
assert(alloc_call_count == 2 and free_call_count == 2 and resize_call_count == 1)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 24):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 24)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
local es, ec = evo.multi_spawn(20, { [f1] = 48 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.remove(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == 44)
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 44) end
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 0)
evo.destroy(e1)
for i = 1, ec do evo.destroy(es[i]) end
assert(alloc_call_count == 2 and free_call_count == 1 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 2 and free_call_count == 2 and resize_call_count == 0)
end
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 100):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 100)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
local es, ec = evo.multi_spawn(20, { [f1] = 48 })
for i = 1, ec do assert(evo.has(es[i], f1) and evo.get(es[i], f1) == nil) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.destroy(e1)
for i = 1, ec do evo.destroy(es[i]) end
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
evo.collect_garbage()
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
end
do
local realloc = ctor_realloc()
local f1 = evo.builder():realloc(realloc):build()
alloc_call_count, free_call_count, resize_call_count = 0, 0, 0
do
local e1 = evo.builder():set(f1, 42):build()
assert(evo.has(e1, f1) and evo.get(e1, f1) == 42)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.destroy(e1)
assert(not evo.has(e1, f1) and evo.get(e1, f1) == nil)
assert(alloc_call_count == 1 and free_call_count == 0 and resize_call_count == 0)
evo.set(f1, evo.TAG)
assert(alloc_call_count == 1 and free_call_count == 1 and resize_call_count == 0)
end
end
end

View File

@@ -1,5 +1,7 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES)
@@ -243,3 +245,143 @@ do
end
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.REQUIRES, { f4 })
do
local e1 = evo.builder():set(f1):spawn()
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(evo.has(e1, f3) and evo.get(e1, f3) == true)
assert(evo.has(e1, f4) and evo.get(e1, f4) == true)
local e2 = evo.builder():set(f2):spawn()
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(evo.has(e2, f3) and evo.get(e2, f3) == true)
assert(evo.has(e2, f4) and evo.get(e2, f4) == true)
local e3 = evo.builder():set(f3):spawn()
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
do
local e1 = evo.id()
evo.set(e1, f1)
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(evo.has(e1, f3) and evo.get(e1, f3) == true)
assert(evo.has(e1, f4) and evo.get(e1, f4) == true)
local e2 = evo.id()
evo.set(e2, f2)
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(evo.has(e2, f3) and evo.get(e2, f3) == true)
assert(evo.has(e2, f4) and evo.get(e2, f4) == true)
local e3 = evo.id()
evo.set(e3, f3)
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
evo.remove(f2, evo.REQUIRES)
do
local e1 = evo.builder():set(f1):spawn()
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(not evo.has(e1, f3) and evo.get(e1, f3) == nil)
assert(not evo.has(e1, f4) and evo.get(e1, f4) == nil)
local e2 = evo.builder():set(f2):spawn()
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(not evo.has(e2, f3) and evo.get(e2, f3) == nil)
assert(not evo.has(e2, f4) and evo.get(e2, f4) == nil)
local e3 = evo.builder():set(f3):spawn()
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
do
local e1 = evo.id()
evo.set(e1, f1)
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(not evo.has(e1, f3) and evo.get(e1, f3) == nil)
assert(not evo.has(e1, f4) and evo.get(e1, f4) == nil)
local e2 = evo.id()
evo.set(e2, f2)
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(not evo.has(e2, f3) and evo.get(e2, f3) == nil)
assert(not evo.has(e2, f4) and evo.get(e2, f4) == nil)
local e3 = evo.id()
evo.set(e3, f3)
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
evo.set(f2, evo.REQUIRES, { f4 })
do
local e1 = evo.builder():set(f1):spawn()
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(not evo.has(e1, f3) and evo.get(e1, f3) == nil)
assert(evo.has(e1, f4) and evo.get(e1, f4) == true)
local e2 = evo.builder():set(f2):spawn()
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(not evo.has(e2, f3) and evo.get(e2, f3) == nil)
assert(evo.has(e2, f4) and evo.get(e2, f4) == true)
local e3 = evo.builder():set(f3):spawn()
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
do
local e1 = evo.id()
evo.set(e1, f1)
assert(evo.has(e1, f1) and evo.get(e1, f1) == true)
assert(evo.has(e1, f2) and evo.get(e1, f2) == true)
assert(not evo.has(e1, f3) and evo.get(e1, f3) == nil)
assert(evo.has(e1, f4) and evo.get(e1, f4) == true)
local e2 = evo.id()
evo.set(e2, f2)
assert(not evo.has(e2, f1) and evo.get(e2, f1) == nil)
assert(evo.has(e2, f2) and evo.get(e2, f2) == true)
assert(not evo.has(e2, f3) and evo.get(e2, f3) == nil)
assert(evo.has(e2, f4) and evo.get(e2, f4) == true)
local e3 = evo.id()
evo.set(e3, f3)
assert(not evo.has(e3, f1) and evo.get(e3, f1) == nil)
assert(not evo.has(e3, f2) and evo.get(e3, f2) == nil)
assert(evo.has(e3, f3) and evo.get(e3, f3) == true)
assert(evo.has(e3, f4) and evo.get(e3, f4) == true)
end
end

View File

@@ -0,0 +1,331 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
do
local e = evo.spawn()
assert(evo.alive(e) and evo.empty(e))
end
do
local e = evo.spawn({})
assert(evo.alive(e) and evo.empty(e))
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f1, f3 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = 'hello' })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == 'hello')
assert(evo.has(e, f3) and evo.get(e, f3) == 21)
end
end
do
local f1, f2, f3, f4 = evo.id(4)
evo.set(f2, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.REQUIRES, { f1, f3, f4 })
evo.set(f3, evo.DEFAULT, 21)
evo.set(f3, evo.DUPLICATE, function(v) return v * 3 end)
evo.set(f3, evo.REQUIRES, { f2 })
do
local e = evo.spawn({ [f1] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
end
do
local e = evo.spawn({ [f1] = 42, [f2] = true })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3, f4))
assert(evo.has(e, f1) and evo.get(e, f1) == 42)
assert(evo.has(e, f2) and evo.get(e, f2) == true)
assert(evo.has(e, f3) and evo.get(e, f3) == 21 * 3)
assert(evo.has(e, f4) and evo.get(e, f4) == true)
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
f3_set_count, f3_inserted_count = 0, 0
local e = evo.spawn({ [f1] = 'hello', [f2] = 42 })
assert(evo.alive(e) and not evo.empty(e) and evo.locate(e) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 and f2_inserted_sum == 42)
assert(f3_set_count == 1 and f3_inserted_count == 1)
end
end
do
do
local es, ec = evo.multi_spawn(2)
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
do
local es, ec = evo.multi_spawn(2, {})
assert(#es == 2 and ec == 2)
for i = 1, ec do
assert(evo.alive(es[i]) and evo.empty(es[i]))
end
end
end
do
local f1, f2 = evo.id(2)
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
end
end
do
local es, ec = evo.multi_spawn(3, { [f1] = 42, [f2] = 'hello' })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(3, { [f1] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
do
local es, ec = evo.multi_spawn(1, { [f1] = 42 })
assert(#es == 1 and ec == 1)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == true)
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f1, evo.REQUIRES, { f2, f3 })
evo.set(f2, evo.DEFAULT, 'hello')
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == true)
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world', [f3] = false })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == 42)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world')
assert(evo.has(es[i], f3) and evo.get(es[i], f3) == false)
end
end
end
do
local f1, f2 = evo.id(2)
evo.set(f1, evo.REQUIRES, { f2 })
evo.set(f1, evo.DUPLICATE, function() return nil end)
evo.set(f2, evo.DEFAULT, 'hello')
evo.set(f2, evo.DUPLICATE, function(v) return v .. '!' end)
do
local es, ec = evo.multi_spawn(4, { [f1] = 42 })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f1] = 42, [f2] = 'world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2))
assert(evo.has(es[i], f1) and evo.get(es[i], f1) == true)
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'world!')
end
end
do
local es, ec = evo.multi_spawn(4, { [f2] = 'hello world' })
assert(#es == 4 and ec == 4)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f2))
assert(evo.has(es[i], f2) and evo.get(es[i], f2) == 'hello world!')
end
end
end
do
local f1, f2, f3 = evo.id(3)
evo.set(f2, evo.REQUIRES, { f3 })
evo.set(f3, evo.TAG)
local f2_set_sum, f2_inserted_sum = 0, 0
local f3_set_count, f3_inserted_count = 0, 0
evo.set(f2, evo.ON_SET, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_set_sum = f2_set_sum + c
end)
evo.set(f2, evo.ON_INSERT, function(e, f, c)
assert(c == 42)
assert(evo.get(e, f) == c)
assert(f == f2)
f2_inserted_sum = f2_inserted_sum + c
end)
evo.set(f3, evo.ON_SET, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_set_count = f3_set_count + 1
end)
evo.set(f3, evo.ON_INSERT, function(e, f, c)
assert(c == nil)
assert(evo.get(e, f) == c)
assert(f == f3)
f3_inserted_count = f3_inserted_count + 1
end)
do
local es, ec = evo.multi_spawn(3, { [f1] = 'hello', [f2] = 42 })
assert(#es == 3 and ec == 3)
for i = 1, ec do
assert(evo.alive(es[i]) and not evo.empty(es[i]) and evo.locate(es[i]) == evo.chunk(f1, f2, f3))
assert(f2_set_sum == 42 * 3 and f2_inserted_sum == 42 * 3)
assert(f3_set_count == 3 and f3_inserted_count == 3)
end
end
end

View File

@@ -1,5 +1,7 @@
local evo = require 'evolved'
evo.debug_mode(true)
do
local f1, f2, f3 = evo.id(3)

View File

@@ -1,860 +0,0 @@
local basics = require 'develop.basics'
basics.unload 'evolved'
local evo = require 'evolved'
local N = 1000
local B = evo.builder()
local F1, F2, F3, F4, F5 = evo.id(5)
local Q1 = evo.builder():include(F1):spawn()
local R1 = evo.builder():require(F1):spawn()
local R2 = evo.builder():require(F1, F2):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R4 = evo.builder():require(F1, F2, F3, F4):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables', N),
---@param tables table[]
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
end, function()
return {}
end)
basics.describe_bench(string.format('create and collect %d tables', N),
---@param tables table[]
function(tables)
for i = 1, N do
local t = {}
tables[i] = t
end
for i = 1, #tables do
tables[i] = nil
end
collectgarbage('collect')
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables with 1 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 2 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 3 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 4 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
tables[i] = e
end
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 5 component / AoS', N),
---@param tables table
function(tables)
for i = 1, N do
local e = {}
e[F1] = true
e[F2] = true
e[F3] = true
e[F4] = true
e[F5] = true
tables[i] = e
end
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create %d tables with 1 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
for i = 1, N do
local e = {}
fs1[i] = true
tables[i] = e
end
tables[F1] = fs1
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 2 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 3 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
for i = 1, N do
local e = {}
fs1[i] = true
fs2[i] = true
fs3[i] = true
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 4 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
for i = 1, N do
local e = {}
fs1[i] = i
fs2[i] = i
fs3[i] = i
fs4[i] = i
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
end, function()
return {}
end)
basics.describe_bench(string.format('create %d tables with 5 component / SoA', N),
---@param tables table
function(tables)
local fs1 = {}
local fs2 = {}
local fs3 = {}
local fs4 = {}
local fs5 = {}
for i = 1, N do
local e = {}
fs1[i] = i
fs2[i] = i
fs3[i] = i
fs4[i] = i
fs5[i] = i
tables[i] = e
end
tables[F1] = fs1
tables[F2] = fs2
tables[F3] = fs3
tables[F4] = fs4
tables[F5] = fs5
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local destroy = evo.destroy
for i = 1, N do
local e = id()
entities[i] = e
end
for i = #entities, 1, -1 do
destroy(entities[i])
end
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 1 component', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
entities[i] = e
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / defer', N),
---@param entities evolved.id[]
function(entities)
local id = evo.id
local set = evo.set
evo.defer()
for i = 1, N do
local e = id()
set(e, F1)
set(e, F2)
set(e, F3)
set(e, F4)
set(e, F5)
entities[i] = e
end
evo.commit()
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
set(B, F4)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / builder', N),
---@param entities evolved.id[]
function(entities)
local set = B.set
local spawn = B.spawn
for i = 1, N do
set(B, F1)
set(B, F2)
set(B, F3)
set(B, F4)
set(B, F5)
entities[i] = spawn(B)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 components / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R1] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R2] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R3] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R4] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 requires / spawn', N),
---@param entities evolved.id[]
function(entities)
local spawn = evo.spawn
local components = { [R5] = true }
for i = 1, N do
entities[i] = spawn(components)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
print '----------------------------------------'
basics.describe_bench(string.format('create and destroy %d entities with 1 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R1] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 2 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R2] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 3 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R3] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 4 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R4] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)
basics.describe_bench(string.format('create and destroy %d entities with 5 requires / clone', N),
---@param entities evolved.id[]
function(entities)
local clone = evo.clone
local prefab = evo.spawn({ [R5] = true })
for i = 1, N do
entities[i] = clone(prefab)
end
evo.batch_destroy(Q1)
end, function()
return {}
end)

View File

@@ -1,374 +0,0 @@
local basics = require 'develop.basics'
basics.unload 'evolved'
local evo = require 'evolved'
local tiny = require 'develop.3rdparty.tiny'
local N = 1000
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Entity Cycle: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) world:addEntity({ b = e.a }) end
A.postProcess = function(_) world:refresh() end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) world:removeEntity(e) end
B.postProcess = function(_) world:refresh() end
world:addSystem(A)
world:addSystem(B)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Entity Cycle (Defer): %d entities', N),
function(a, b, A, B)
evo.defer()
do
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
evo.set(evo.id(), b, as[i])
end
end
end
evo.commit()
evo.batch_destroy(B)
end, function()
local a, b = evo.id(2)
for i = 1, N do
evo.builder():set(a, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
return a, b, A, B
end, function(_, _, A, _)
evo.batch_destroy(A)
end)
basics.describe_bench(string.format('Evolved Entity Cycle (Manual): %d entities', N),
function(a, b, A, B)
local to_create = {}
local to_create_count = 0
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
to_create_count = to_create_count + 1
to_create[to_create_count] = as[i]
end
end
for i = 1, to_create_count do
local e = evo.id()
evo.set(e, b, to_create[i])
end
evo.batch_destroy(B)
end, function()
local a, b = evo.id(2)
for i = 1, N do
evo.builder():set(a, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
return a, b, A, B
end, function(_, _, A, _)
evo.batch_destroy(A)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Simple Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i, b = i })
world:addEntity({ a = i, b = i, c = i })
world:addEntity({ a = i, b = i, c = i, d = i })
world:addEntity({ a = i, b = i, c = i, e = i })
end
local AB = tiny.processingSystem()
AB.filter = tiny.requireAll('a', 'b')
AB.process = function(_, e) e.a, e.b = e.b, e.a end
local CD = tiny.processingSystem()
CD.filter = tiny.requireAll('c', 'd')
CD.process = function(_, e) e.c, e.d = e.d, e.c end
local CE = tiny.processingSystem()
CE.filter = tiny.requireAll('c', 'e')
CE.process = function(_, e) e.c, e.e = e.e, e.c end
world:addSystem(AB)
world:addSystem(CD)
world:addSystem(CE)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Simple Iteration: %d entities', N),
---@param a evolved.entity
---@param b evolved.entity
---@param c evolved.entity
---@param d evolved.entity
---@param e evolved.entity
---@param AB evolved.query
---@param CD evolved.query
---@param CE evolved.query
function(a, b, c, d, e, AB, CD, CE)
for chunk, _, entity_count in evo.execute(AB) do
local as, bs = chunk:components(a, b)
for i = 1, entity_count do
as[i], bs[i] = bs[i], as[i]
end
end
for chunk, _, entity_count in evo.execute(CD) do
local cs, ds = chunk:components(c, d)
for i = 1, entity_count do
cs[i], ds[i] = ds[i], cs[i]
end
end
for chunk, _, entity_count in evo.execute(CE) do
local cs, es = chunk:components(c, e)
for i = 1, entity_count do
cs[i], es[i] = es[i], cs[i]
end
end
end, function()
local a, b, c, d, e = evo.id(5)
for i = 1, N do
evo.builder():set(a, i):set(b, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):set(d, i):spawn()
evo.builder():set(a, i):set(b, i):set(c, i):set(e, i):spawn()
end
local AB = evo.builder():include(a, b):spawn()
local CD = evo.builder():include(c, d):spawn()
local CE = evo.builder():include(c, e):spawn()
return a, b, c, d, e, AB, CD, CE
end, function(_, _, _, _, _, AB, CD, CE)
evo.batch_destroy(AB)
evo.batch_destroy(CD)
evo.batch_destroy(CE)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Packed Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
for i = 1, N do
world:addEntity({ a = i, b = i, c = i, d = i, e = i })
end
local A = tiny.processingSystem()
A.filter = tiny.requireAll('a')
A.process = function(_, e) e.a = e.a * 2 end
local B = tiny.processingSystem()
B.filter = tiny.requireAll('b')
B.process = function(_, e) e.b = e.b * 2 end
local C = tiny.processingSystem()
C.filter = tiny.requireAll('c')
C.process = function(_, e) e.c = e.c * 2 end
local D = tiny.processingSystem()
D.filter = tiny.requireAll('d')
D.process = function(_, e) e.d = e.d * 2 end
local E = tiny.processingSystem()
E.filter = tiny.requireAll('e')
E.process = function(_, e) e.e = e.e * 2 end
world:addSystem(A)
world:addSystem(B)
world:addSystem(C)
world:addSystem(D)
world:addSystem(E)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Packed Iteration: %d entities', N),
---@param a evolved.entity
---@param b evolved.entity
---@param c evolved.entity
---@param d evolved.entity
---@param e evolved.entity
---@param A evolved.query
---@param B evolved.query
---@param C evolved.query
---@param D evolved.query
---@param E evolved.query
function(a, b, c, d, e, A, B, C, D, E)
for chunk, _, entity_count in evo.execute(A) do
local as = chunk:components(a)
for i = 1, entity_count do
as[i] = as[i] * 2
end
end
for chunk, _, entity_count in evo.execute(B) do
local bs = chunk:components(b)
for i = 1, entity_count do
bs[i] = bs[i] * 2
end
end
for chunk, _, entity_count in evo.execute(C) do
local cs = chunk:components(c)
for i = 1, entity_count do
cs[i] = cs[i] * 2
end
end
for chunk, _, entity_count in evo.execute(D) do
local ds = chunk:components(d)
for i = 1, entity_count do
ds[i] = ds[i] * 2
end
end
for chunk, _, entity_count in evo.execute(E) do
local es = chunk:components(e)
for i = 1, entity_count do
es[i] = es[i] * 2
end
end
end, function()
local a, b, c, d, e = evo.id(5)
for i = 1, N do
evo.builder():set(a, i):set(b, i):set(c, i):set(d, i):set(e, i):spawn()
end
local A = evo.builder():include(a):spawn()
local B = evo.builder():include(b):spawn()
local C = evo.builder():include(c):spawn()
local D = evo.builder():include(d):spawn()
local E = evo.builder():include(e):spawn()
return a, b, c, d, e, A, B, C, D, E
end, function(_, _, _, _, _, A, _, _, _, _)
evo.batch_destroy(A)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Tiny Fragmented Iteration: %d entities', N),
function(world)
world:update(0.016)
end, function()
local world = tiny.world()
---@type string[]
local chars = {}
for i = 1, 26 do
chars[i] = string.char(string.byte('a') + i - 1)
end
for _, char in ipairs(chars) do
for i = 1, N do
world:addEntity({ [char] = i, data = i })
end
end
local Data = tiny.processingSystem()
Data.filter = tiny.requireAll('data')
Data.process = function(_, e) e.data = e.data * 2 end
local Last = tiny.processingSystem()
Last.filter = tiny.requireAll('z')
Last.process = function(_, e) e.z = e.z * 2 end
world:addSystem(Data)
world:addSystem(Last)
world:refresh()
return world
end)
basics.describe_bench(string.format('Evolved Fragmented Iteration: %d entities', N),
---@param data evolved.entity
---@param last evolved.entity
---@param Data evolved.query
---@param Last evolved.query
function(data, last, Data, Last)
for chunk, _, entity_count in evo.execute(Data) do
local ds = chunk:components(data)
for i = 1, entity_count do
ds[i] = ds[i] * 2
end
end
for chunk, _, entity_count in evo.execute(Last) do
local ls = chunk:components(last)
for i = 1, entity_count do
ls[i] = ls[i] * 2
end
end
end, function()
local data = evo.id()
---@type evolved.fragment[]
local chars = {}
for i = 1, 26 do
chars[i] = evo.id()
end
for _, char in ipairs(chars) do
for i = 1, N do
evo.builder():set(char, i):set(data, i):spawn()
end
end
local Data = evo.builder():include(data):spawn()
local Last = evo.builder():include(chars[#chars]):spawn()
return data, chars[#chars], Data, Last
end, function(_, _, Data, _)
evo.batch_destroy(Data)
end)

285
evolved.d.tl Normal file
View File

@@ -0,0 +1,285 @@
local record Evolved
interface Id end
type Entity = Id
type Fragment = Id
type Query = Id
type System = Id
interface EachState end
interface ExecuteState end
type EachIterator = function(state?: EachState): Fragment, any
type ExecuteIterator = function(state?: ExecuteState): Chunk, { Entity }, integer
interface Chunk
alive: function(self: Chunk): boolean
empty: function(self: Chunk): boolean
has: function(self: Chunk, fragment: Fragment): boolean
has_all: function(self: Chunk, ...: Fragment): boolean
has_any: function(self: Chunk, ...: Fragment): boolean
entities: function(self: Chunk): { Entity }, integer
fragments: function(self: Chunk): { Fragment }, integer
components: function(self: Chunk)
components: function<C1>(self: Chunk, f1: Fragment): { C1 }
components: function<C1, C2>(self: Chunk, f1: Fragment, f2: Fragment): { C1 }, { C2 }
components: function<C1, C2, C3>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment): { C1 }, { C2 }, { C3 }
components: function<C1, C2, C3, C4>(self: Chunk, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): { C1 }, { C2 }, { C3 }, { C4 }
end
interface Builder
build: function(self: Builder,
prefab?: Entity,
component_mapper?: function(Chunk, integer)): Entity
multi_build: function(self: Builder,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_build_nr: function(self: Builder,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer))
multi_build_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab?: Entity,
component_mapper?: function(Chunk, integer, integer))
spawn: function(self: Builder,
component_mapper?: function(Chunk, integer)): Entity
multi_spawn: function(self: Builder,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_spawn_nr: function(self: Builder,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer))
multi_spawn_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
component_mapper?: function(Chunk, integer, integer))
clone: function(self: Builder,
prefab: Entity,
component_mapper?: function(Chunk, integer)): Entity
multi_clone: function(self: Builder,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_clone_nr: function(self: Builder,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, integer))
multi_clone_to: function(self: Builder,
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab: Entity,
component_mapper?: function(Chunk, integer, integer))
has: function(self: Builder, fragment: Fragment): boolean
has_all: function(self: Builder, ...: Fragment): boolean
has_any: function(self: Builder, ...: Fragment): boolean
get: function(self: Builder)
get: function<C1>(self: Builder, f1: Fragment): C1 | nil
get: function<C1, C2>(self: Builder, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(self: Builder, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(self: Builder, fragment: Fragment, component?: Component): Builder
remove: function(self: Builder, ...: Fragment): Builder
clear: function(self: Builder): Builder
tag: function(self: Builder): Builder
name: function(self: Builder, name: string): Builder
unique: function(self: Builder): Builder
explicit: function(self: Builder): Builder
internal: function(self: Builder): Builder
default: function<Component>(self: Builder, default: Component): Builder
duplicate: function<Component>(self: Builder, duplicate: function(Component): Component): Builder
realloc: function<Component>(self: Builder, realloc: function({ Component } | nil, integer, integer): { Component } | nil): Builder
compmove: function<Component>(self: Builder, compmove: function({ Component }, integer, integer, integer, { Component })): Builder
prefab: function(self: Builder): Builder
disabled: function(self: Builder): Builder
include: function(self: Builder, ...: Fragment): Builder
exclude: function(self: Builder, ...: Fragment): Builder
variant: function(self: Builder, ...: Fragment): Builder
require: function(self: Builder, ...: Fragment): Builder
on_set: function<Component>(self: Builder, on_set: function(Entity, Fragment, ? Component, ? Component)): Builder
on_assign: function<Component>(self: Builder, on_assign: function(Entity, Fragment, ? Component, ? Component)): Builder
on_insert: function<Component>(self: Builder, on_insert: function(Entity, Fragment, ? Component)): Builder
on_remove: function<Component>(self: Builder, on_remove: function(Entity, Fragment, ? Component)): Builder
group: function(self: Builder, group: System): Builder
query: function(self: Builder, query: Query): Builder
execute: function(self: Builder, execute: function(Chunk, {Entity}, integer, ...: any)): Builder
prologue: function(self: Builder, prologue: function(...: any)): Builder
epilogue: function(self: Builder, epilogue: function(...: any)): Builder
destruction_policy: function(self: Builder, destruction_policy: Id): Builder
end
TAG: Fragment
NAME: Fragment
UNIQUE: Fragment
EXPLICIT: Fragment
INTERNAL: Fragment
DEFAULT: Fragment
DUPLICATE: Fragment
REALLOC: Fragment
COMPMOVE: Fragment
PREFAB: Fragment
DISABLED: Fragment
INCLUDES: Fragment
EXCLUDES: Fragment
VARIANTS: Fragment
REQUIRES: Fragment
ON_SET: Fragment
ON_ASSIGN: Fragment
ON_INSERT: Fragment
ON_REMOVE: Fragment
GROUP: Fragment
QUERY: Fragment
EXECUTE: Fragment
PROLOGUE: Fragment
EPILOGUE: Fragment
DESTRUCTION_POLICY: Fragment
DESTRUCTION_POLICY_DESTROY_ENTITY: Id
DESTRUCTION_POLICY_REMOVE_FRAGMENT: Id
id: function(count?: integer): Id...
name: function(...: Id): string...
pack: function(primary: integer, secondary: integer): Id
unpack: function(id: Id): integer, integer
defer: function(): boolean
depth: function(): integer
commit: function(): boolean
cancel: function(): boolean
spawn: function(
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer)): Entity
multi_spawn: function(
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_spawn_nr: function(
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
multi_spawn_to: function(
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
clone: function(
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer)): Entity
multi_clone: function(
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer)): { Entity }, integer
multi_clone_nr: function(
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
multi_clone_to: function(
out_entity_list: { Entity },
out_entity_first: integer,
entity_count: integer,
prefab: Entity,
component_table?: { Fragment: any },
component_mapper?: function(Chunk, integer, integer))
alive: function(entity: Entity): boolean
alive_all: function(...: Entity): boolean
alive_any: function(...: Entity): boolean
empty: function(entity: Entity): boolean
empty_all: function(...: Entity): boolean
empty_any: function(...: Entity): boolean
has: function(entity: Entity, fragment: Fragment): boolean
has_all: function(entity: Entity, ...: Fragment): boolean
has_any: function(entity: Entity, ...: Fragment): boolean
get: function(entity: Entity)
get: function<C1>(entity: Entity, f1: Fragment): C1 | nil
get: function<C1, C2>(entity: Entity, f1: Fragment, f2: Fragment): C1 | nil, C2 | nil
get: function<C1, C2, C3>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment): C1 | nil, C2 | nil, C3 | nil
get: function<C1, C2, C3, C4>(entity: Entity, f1: Fragment, f2: Fragment, f3: Fragment, f4: Fragment): C1 | nil, C2 | nil, C3 | nil, C4 | nil
set: function<Component>(entity: Entity, fragment: Fragment, component?: Component)
remove: function(entity: Entity, ...: Fragment)
clear: function(...: Entity)
destroy: function(...: Entity)
batch_set: function<Component>(query: Query, fragment: Fragment, component?: Component)
batch_remove: function(query: Query, ...: Fragment)
batch_clear: function(...: Query)
batch_destroy: function(...: Query)
each: function(entity: Entity): EachIterator, EachState | nil
execute: function(query: Query): ExecuteIterator, ExecuteState | nil
locate: function(entity: Entity): Chunk | nil, integer
lookup: function(name: string): Entity | nil
multi_lookup: function(name: string): { Entity }, integer
multi_lookup_to: function(out_entity_list: { Entity }, out_entity_first: integer, name: string): integer
process: function(...: System)
process_with: function(system: System, ...: any)
debug_mode: function(yesno: boolean)
collect_garbage: function(no_shrink?: boolean)
chunk: function(fragment: Fragment, ...: Fragment): Chunk, { Entity }, integer
builder: function(): Builder
end
return Evolved

File diff suppressed because it is too large Load Diff

10
example/conf.lua Normal file
View File

@@ -0,0 +1,10 @@
if os.getenv('LOCAL_LUA_DEBUGGER_VSCODE') == '1' then
require('lldebugger').start()
end
---@type love.conf
function love.conf(t)
t.window.title = 'Evolved Example'
t.window.width = 640
t.window.height = 480
end

170
example/main.lua Normal file
View File

@@ -0,0 +1,170 @@
local evolved = require 'evolved'
local STAGES = {
ON_SETUP = evolved.builder()
:name('STAGES.ON_SETUP')
:build(),
ON_UPDATE = evolved.builder()
:name('STAGES.ON_UPDATE')
:build(),
ON_RENDER = evolved.builder()
:name('STAGES.ON_RENDER')
:build(),
}
local FRAGMENTS = {
POSITION_X = evolved.builder()
:name('FRAGMENTS.POSITION_X')
:default(0)
:build(),
POSITION_Y = evolved.builder()
:name('FRAGMENTS.POSITION_Y')
:default(0)
:build(),
VELOCITY_X = evolved.builder()
:name('FRAGMENTS.VELOCITY_X')
:default(0)
:build(),
VELOCITY_Y = evolved.builder()
:name('FRAGMENTS.VELOCITY_Y')
:default(0)
:build(),
}
local PREFABS = {
CIRCLE = evolved.builder()
:name('PREFABS.CIRCLE')
:prefab()
:set(FRAGMENTS.POSITION_X)
:set(FRAGMENTS.POSITION_Y)
:set(FRAGMENTS.VELOCITY_X)
:set(FRAGMENTS.VELOCITY_Y)
:build(),
}
---
---
---
---
---
evolved.builder()
:name('SYSTEMS.STARTUP')
:group(STAGES.ON_SETUP)
:prologue(function()
evolved.multi_clone_nr(500, PREFABS.CIRCLE, nil, function(chunk, b_place, e_place)
local screen_width, screen_height = love.graphics.getDimensions()
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
---@type number[], number[]
local velocity_xs, velocity_ys = chunk:components(
FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
for i = b_place, e_place do
local px = math.random() * screen_width
local py = math.random() * screen_height
local vx = math.random(-100, 100)
local vy = math.random(-100, 100)
position_xs[i], position_ys[i] = px, py
velocity_xs[i], velocity_ys[i] = vx, vy
end
end)
end):build()
evolved.builder()
:name('SYSTEMS.MOVEMENT')
:group(STAGES.ON_UPDATE)
:include(FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
:include(FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
:execute(function(chunk, _, entity_count, delta_time)
local screen_width, screen_height = love.graphics.getDimensions()
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
---@type number[], number[]
local velocity_xs, velocity_ys = chunk:components(
FRAGMENTS.VELOCITY_X, FRAGMENTS.VELOCITY_Y)
for i = 1, entity_count do
local px, py = position_xs[i], position_ys[i]
local vx, vy = velocity_xs[i], velocity_ys[i]
px = px + vx * delta_time
py = py + vy * delta_time
if px < 0 and vx < 0 then
vx = -vx
elseif px > screen_width and vx > 0 then
vx = -vx
end
if py < 0 and vy < 0 then
vy = -vy
elseif py > screen_height and vy > 0 then
vy = -vy
end
position_xs[i], position_ys[i] = px, py
velocity_xs[i], velocity_ys[i] = vx, vy
end
end):build()
evolved.builder()
:name('SYSTEMS.RENDERING')
:group(STAGES.ON_RENDER)
:include(FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
:execute(function(chunk, _, entity_count)
---@type number[], number[]
local position_xs, position_ys = chunk:components(
FRAGMENTS.POSITION_X, FRAGMENTS.POSITION_Y)
for i = 1, entity_count do
local x, y = position_xs[i], position_ys[i]
love.graphics.circle('fill', x, y, 5)
end
end):build()
evolved.builder()
:name('SYSTEMS.DEBUGGING')
:group(STAGES.ON_RENDER)
:epilogue(function()
local fps = love.timer.getFPS()
local mem = collectgarbage('count')
love.graphics.print(string.format('FPS: %d', fps), 10, 10)
love.graphics.print(string.format('MEM: %d KB', mem), 10, 30)
end):build()
---
---
---
---
---
---@type love.load
function love.load()
evolved.process(STAGES.ON_SETUP)
end
---@type love.update
function love.update(dt)
evolved.process_with(STAGES.ON_UPDATE, dt)
end
---@type love.draw
function love.draw()
evolved.process(STAGES.ON_RENDER)
end
---@type love.keypressed
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
end
end

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.10.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.10.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.3.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.3.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.4.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.4.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.5.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.5.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.6.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.6.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.7.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.7.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.8.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.8.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}

View File

@@ -0,0 +1,34 @@
rockspec_format = "3.0"
package = "evolved.lua"
version = "1.9.0-0"
source = {
url = "git://github.com/BlackMATov/evolved.lua",
tag = "v1.9.0",
}
description = {
homepage = "https://github.com/BlackMATov/evolved.lua",
summary = "Evolved ECS (Entity-Component-System) for Lua",
detailed = [[
`evolved.lua` is a fast and flexible ECS (Entity-Component-System) library for Lua.
It is designed to be simple and easy to use, while providing all the features needed to create complex systems with blazing performance.
]],
license = "MIT",
labels = {
"ecs",
"entity",
"entities",
"component",
"components",
"entity-component",
"entity-component-system",
},
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
evolved = "evolved.lua",
}
}