101 Commits

Author SHA1 Message Date
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
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
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
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
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
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
50 changed files with 8898 additions and 2824 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,

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

622
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
# Roadmap
## Backlog
- Queries can cache major chunks to avoid finding them every time.
- 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?
## Known Issues
- Required fragments are slower than they should be

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,26 +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.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'
require 'develop.untests'
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'
@@ -30,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

@@ -6,16 +6,35 @@ 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)
local Q1 = evo.builder():include(F1):spawn()
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)
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
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),
basics.describe_bench(
string.format('Clone Benchmarks: Simple Clone | %d entities with 1 component', N),
function()
local clone = evo.clone
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 components', N),
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
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 components', N),
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
@@ -51,53 +132,180 @@ basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entitie
clone(prefab)
end
evo.batch_destroy(Q1)
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),
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 { [R1] = true }
local prefab = evo.spawn { [RF1] = true }
evo.remove(prefab, F1)
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 3 required components', N),
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 { [R3] = true }
local prefab = evo.spawn { [RF1] = true }
evo.defer()
for _ = 1, N do
clone(prefab)
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Simple Clone | %d entities with 5 required components', N),
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 { [R5] = true }
local prefab = evo.spawn { [RD1] = true }
for _ = 1, N do
clone(prefab)
end
evo.batch_destroy(Q1)
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),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
@@ -105,10 +313,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true }
evo.defer()
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [D1] = true }
multi_clone(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 = evo.multi_clone
@@ -116,10 +351,37 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 3 components', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true }
multi_clone(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 = evo.multi_clone
@@ -127,40 +389,147 @@ basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities
multi_clone(N, prefab)
evo.batch_destroy(Q1)
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 = evo.multi_clone
local prefab = evo.spawn { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R1] = true }
local prefab = evo.spawn { [RF1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Defer Clone | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R3] = true }
local prefab = evo.spawn { [RF1] = true }
evo.defer()
multi_clone(N, prefab)
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Clone Benchmarks: Multi Clone | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Clone Benchmarks: Multi Clone With Defaults | %d entities with 1 required component', N),
function()
local multi_clone = evo.multi_clone
local prefab = evo.spawn { [R5] = true }
local prefab = evo.spawn { [RD1] = true }
multi_clone(N, prefab)
evo.batch_destroy(Q1)
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 = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [RF123] = true }
evo.defer()
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [RD123] = true }
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [RF12345] = true }
evo.defer()
multi_clone(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 = evo.multi_clone
local prefab = evo.spawn { [RD12345] = true }
multi_clone(N, prefab)
evo.batch_destroy(QD1)
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

@@ -6,16 +6,35 @@ 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)
local Q1 = evo.builder():include(F1):spawn()
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)
local R1 = evo.builder():require(F1):spawn()
local R3 = evo.builder():require(F1, F2, F3):spawn()
local R5 = evo.builder():require(F1, F2, F3, F4, F5):spawn()
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),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 component', N),
function()
local spawn = evo.spawn
@@ -25,10 +44,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 components', N),
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
@@ -38,10 +88,41 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 components', N),
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
@@ -51,53 +132,177 @@ basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entitie
spawn(components)
end
evo.batch_destroy(Q1)
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),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R1] = true }
local components = { [RF1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Simple Defer Spawn | %d entities with 1 required component', N),
function()
local spawn = evo.spawn
local components = { [R3] = true }
local components = { [RF1] = true }
evo.defer()
for _ = 1, N do
spawn(components)
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Simple Spawn | %d entities with 5 required components', N),
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 = { [R5] = true }
local components = { [RD1] = true }
for _ = 1, N do
spawn(components)
end
evo.batch_destroy(Q1)
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),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 component', N),
function()
local builder = evo.builder():set(F1)
@@ -105,10 +310,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 components', N),
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)
@@ -116,10 +348,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 components', N),
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)
@@ -127,47 +386,155 @@ basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entiti
builder:spawn()
end
evo.batch_destroy(Q1)
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),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R1)
local builder = evo.builder():set(RF1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Defer Spawn | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R3)
local builder = evo.builder():set(RF1)
evo.defer()
for _ = 1, N do
builder:spawn()
end
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Builder Spawn | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Builder Spawn With Defaults | %d entities with 1 required component', N),
function()
local builder = evo.builder():set(R5)
local builder = evo.builder():set(RD1)
for _ = 1, N do
builder:spawn()
end
evo.batch_destroy(Q1)
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),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
@@ -175,10 +542,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true }
evo.defer()
multi_spawn(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 = evo.multi_spawn
local components = { [D1] = true }
multi_spawn(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 = evo.multi_spawn
@@ -186,10 +580,37 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 3 components', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true }
evo.defer()
multi_spawn(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 = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true }
multi_spawn(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 = evo.multi_spawn
@@ -197,12 +618,39 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
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 = evo.multi_spawn
local components = { [F1] = true, [F2] = true, [F3] = true, [F4] = true, [F5] = true }
evo.defer()
multi_spawn(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 = evo.multi_spawn
local components = { [D1] = true, [D2] = true, [D3] = true, [D4] = true, [D5] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
end)
print '----------------------------------------'
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
@@ -210,27 +658,107 @@ basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities
multi_spawn(N, components)
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 3 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Defer Spawn | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R3] = true }
local components = { [F1] = true }
evo.defer()
multi_spawn(N, components)
evo.commit()
evo.batch_destroy(Q1)
evo.batch_destroy(QF1)
end)
basics.describe_bench(string.format('Spawn Benchmarks: Multi Spawn | %d entities with 5 required components', N),
basics.describe_bench(
string.format('Spawn Benchmarks: Multi Spawn With Defaults | %d entities with 1 required component', N),
function()
local multi_spawn = evo.multi_spawn
local components = { [R5] = true }
local components = { [D1] = true }
multi_spawn(N, components)
evo.batch_destroy(Q1)
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 = evo.multi_spawn
local components = { [RF123] = true }
multi_spawn(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 = evo.multi_spawn
local components = { [RF123] = true }
evo.defer()
multi_spawn(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 = evo.multi_spawn
local components = { [RD123] = true }
multi_spawn(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 = evo.multi_spawn
local components = { [RF12345] = true }
multi_spawn(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 = evo.multi_spawn
local components = { [RF12345] = true }
evo.defer()
multi_spawn(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 = evo.multi_spawn
local components = { [RD12345] = true }
multi_spawn(N, components)
evo.batch_destroy(QD1)
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

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

View File

@@ -0,0 +1,399 @@
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

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

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

View File

@@ -0,0 +1,176 @@
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

View File

@@ -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
@@ -6449,3 +6487,650 @@ do
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,302 @@ 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

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)

224
evolved.d.tl Normal file
View File

@@ -0,0 +1,224 @@
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
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
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
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
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
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
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(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.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",
}
}