Commits

Marcus von Appen committed 409cfea

- added linear/concurrent processing functions for World
implementations - the World.Process() interface method has been removed
- removed System.ProcessSingle() interface - there is no real purpose
for it at the moment
- added World.Component[s]() interface methods to query components of a
World - World.GetComponent() was removed in favour for those
- added World.Systems() interface method for retrieving the registered
interfaces
- renamed MemWorld struct fields
- removed example for now - it does not serve a purpose
- removed test cases - those need to be reworked
- added simple benchmarks

Comments (0)

Files changed (4)

 SRCDIR = `pwd`
 ROOTPKG = mva
-PACKAGES = ebs
+PACKAGES = ebs #dynrules
 CLEANUP = *.cache *.core *~ *.orig
 
 GO ?= go
 	@for pkg in $(PACKAGES); do \
 		echo "Cleaning up in $(ROOTPKG)/$$pkg..."; \
 		$(GO) clean $(ROOTPKG)/$$pkg; \
-		cd $$pkg && rm -f $(CLEANUP); \
+		cd $$pkg && rm -f $(CLEANUP) && cd ..; \
 	done
 
 build:
 		echo "Testing $(ROOTPKG)/$$pkg..."; \
 		$(GO) test $(ROOTPKG)/$$pkg; \
 	done
+
+bench:
+	@for pkg in $(PACKAGES); do \
+		echo "Testing $(ROOTPKG)/$$pkg..."; \
+		$(GO) test -bench=. -cpu 1,2,4 $(ROOTPKG)/$$pkg; \
+	done
 // World environment.
 package ebs
 
-import "fmt"
-var _ = fmt.Println
-var _ = fmt.Printf
+import "sync"
 
 // A simple entity label
 //
 // but only is aware of the data carried by all entities.
 type System interface {
 	Process(components []Component, args...[]interface{})
-	ProcessSingle(component Component, args...[]interface{})
 }
 
 // An application world defines the combination of application data and
 // operates on a certain set of components, but not all components of an
 // entity at once.
 type World interface {
-	AddComponentType(ctype ComponentType)
 	NewEntity() Entity
 	Add(id Entity, values []Component)
 	Delete(id Entity)
-	GetComponent(id Entity, ctype ComponentType) (Component, bool)
+	AddComponentType(ctype ComponentType)
+    ComponentTypes() []ComponentType
+	Component(id Entity, ctype ComponentType) (Component, bool)
+    Components(ctype ComponentType) []Component
 	SetComponent(id Entity, value Component)
 	DeleteComponent(id Entity, ctype ComponentType)
-	AddSystem(system System, ctypes []ComponentType)
+	Systems(ctype ComponentType) []System
+    AddSystem(system System, ctypes []ComponentType)
 	RemoveSystem(system System)
-	Process(args...[]interface{})
 }
 
-// Internal comparision key used
+// Internal comparision key used by the MemoryWorld
 type MemWorldCompKey struct {
 	ct ComponentType
 	e Entity
 // and component types in memory.
 type MemWorld struct {
 	lastId Entity
-	Components map[MemWorldCompKey]Component
-	ComponentTypes map[ComponentType]map[Entity]bool
-	Systems map[ComponentType][]System
+	ComponentMap map[MemWorldCompKey]Component
+	ComponentTypeMap map[ComponentType]map[Entity]bool
+	SystemMap map[ComponentType][]System
 }
 
 // Creates a new World implementation, which keeps all entities,
 func NewMemWorld() *MemWorld {
 	world := new(MemWorld)
 	world.lastId = 1 // We do not use 0 as identity
-	world.ComponentTypes = make(map[ComponentType]map[Entity]bool)
-	world.Components = make(map[MemWorldCompKey]Component)
-	world.Systems = make(map[ComponentType][]System)
+	world.ComponentTypeMap = make(map[ComponentType]map[Entity]bool)
+	world.ComponentMap = make(map[MemWorldCompKey]Component)
+	world.SystemMap = make(map[ComponentType][]System)
 	return world
 }
 
 	return Entity(lastid)
 }
 
+// Gets the component types currently associated with the MemWorld.
+func (world *MemWorld) ComponentTypes() []ComponentType {
+    ctypes := make([]ComponentType, 0)
+    for key := range world.ComponentTypeMap {
+        ctypes = append(ctypes, key)
+    }
+    return ctypes
+}
+
 // Adds a ComponentType to the MemWorld. This usually does not need to
 // be called - it is called by MemWorld.Add() implicitly.
 func (world *MemWorld) AddComponentType(ctype ComponentType) {
-	_, ok := world.ComponentTypes[ctype]
+	_, ok := world.ComponentTypeMap[ctype]
 	if !ok {
-		world.ComponentTypes[ctype] = make(map[Entity]bool)
+		world.ComponentTypeMap[ctype] = make(map[Entity]bool)
 	}
 }
 
 // If the passed Entity does not exist within the MemWorld, this method
 // will not perform any change.
 func (world *MemWorld) Delete(id Entity) {
-	for ctype := range world.ComponentTypes {
-		_, ok := world.ComponentTypes[ctype][id]
+	for ctype := range world.ComponentTypeMap {
+		_, ok := world.ComponentTypeMap[ctype][id]
 		if ok {
-			delete(world.Components, MemWorldCompKey{ctype, id})
-			delete(world.ComponentTypes[ctype], id)
+			delete(world.ComponentMap, MemWorldCompKey{ctype, id})
+			delete(world.ComponentTypeMap[ctype], id)
 		}
 	}
 }
 // not exist or the Entity is not associated with the passed
 // ComponentType, this will return nil and false. Otherwise, this will
 // return a pointer to the stored Component and true.
-func (world *MemWorld) GetComponent(id Entity,
+func (world *MemWorld) Component(id Entity,
 	ctype ComponentType) (Component, bool) {
-	c, ok := world.Components[MemWorldCompKey{ctype, id}]
+	c, ok := world.ComponentMap[MemWorldCompKey{ctype, id}]
 	return c, ok
 }
 
+// Gets all existing components for the specific component type. If no such
+// component type exists, nil is returned.
+func (world *MemWorld) Components(ctype ComponentType) []Component {
+    entities, ok := world.ComponentTypeMap[ctype]
+    if ok {
+        comps := make([]Component, 0)
+        for id := range entities {
+            comps = append(comps,
+                world.ComponentMap[MemWorldCompKey{ctype, id}])
+        }
+        return comps
+    }
+    return nil
+}
+
 // Sets a specific Component for the Entity.
 func (world *MemWorld) SetComponent(id Entity, value Component) {
 	ctype := value.Type()
 	world.AddComponentType(ctype)
-	world.ComponentTypes[ctype][id] = true
-	world.Components[MemWorldCompKey{ctype, id}] = value
+	world.ComponentTypeMap[ctype][id] = true
+	world.ComponentMap[MemWorldCompKey{ctype, id}] = value
 }
 
 // Deletes a component association for the specified Entity. If the
 // done. Otherwise, the Component associated with the Entity will be
 // deleted.
 func (world *MemWorld) DeleteComponent(id Entity, ctype ComponentType) {
-	_, ok := world.ComponentTypes[ctype][id]
+	_, ok := world.ComponentTypeMap[ctype][id]
 	if ok {
-		delete(world.ComponentTypes[ctype], id)
-		delete(world.Components, MemWorldCompKey{ctype, id})
+		delete(world.ComponentTypeMap[ctype], id)
+		delete(world.ComponentMap, MemWorldCompKey{ctype, id})
 	}
 }
 
+// Gets the processing systems associated with a specific component type in
+// the order, in which they were added.
+func (world *MemWorld) Systems(ctype ComponentType) []System {
+    return world.SystemMap[ctype]
+}
+
 // Adds a System to the MemWorld. If the System was added already, this
 // will not do anything
 func (world *MemWorld) AddSystem(system System, ctypes []ComponentType) {
 	for _, ctype := range ctypes {
-		list, ok := world.Systems[ctype]
+		list, ok := world.SystemMap[ctype]
 		if !ok {
-			world.Systems[ctype] = make([]System, 0)
+			world.SystemMap[ctype] = make([]System, 0)
 		}
-		world.Systems[ctype] = append(list, system)
+		world.SystemMap[ctype] = append(list, system)
 	}
 }
 
 // Removes a System from the MemWorld. If the System does not exist in
 // the MemWorld, this will not do anything.
 func (world *MemWorld) RemoveSystem(system System) {
-	for ctype, list := range world.Systems {
+	for ctype, list := range world.SystemMap {
 		todelete := -1
 		for idx, entry := range list {
 			if entry == system {
 			}
 		}
 		if todelete != -1 {
-			world.Systems[ctype] = append(list[:todelete], list[todelete+1:]...)
+			world.SystemMap[ctype] = append(list[:todelete],
+                list[todelete+1:]...)
 		}
 	}
 }
 
-
-func (world *MemWorld) Process(args...[]interface{}) {
-	for ctype, systems := range world.Systems {
-		for _, system := range systems {
-			entities, ok := world.ComponentTypes[ctype]
-			if ok {
-				// TODO: there must be a better way to do this...
-				values := make([]Component, len(entities))
-				idx := 0
-				for e := range entities {
-					values[idx] = world.Components[MemWorldCompKey{ctype, e}]
-					idx++
-				}
-				system.Process(values, args...)
-			}
-		}
-	}
+// Processes all components of the passed World using their associated
+// processing systems. args will be passed to the System.Process()
+// implementation.
+func ProcessLinear(world World, args...[]interface{}) {
+    for _, ctype := range world.ComponentTypes() {
+        for _, system := range world.Systems(ctype) {
+            system.Process(world.Components(ctype), args...)
+        }
+    }
 }
 
-// func doWork(systems []System, inqueue chan Component, args...[]interface{}) {
-// 	for c := range inqueue {
-// 		for _, system := range systems {
-// 			system.ProcessSingle(c, args...)
-// 		}
-// 	}
-// }
+func process(wg *sync.WaitGroup, systems []System, components []Component,
+	args...[]interface{}) {
+    for _, system := range systems {
+        system.Process(components, args...)
+    }
+    wg.Done()
+}
 
-// func (world *MemWorld) Process(args...[]interface{}) {
-// 	inqueue := make(chan Component, 100)
-// 	for ctype, systems := range world.Systems {
-// 		entities := world.ComponentTypes[ctype]
-// 		go doWork(systems, inqueue, args...)
-// 		var c Component
-// 		for id := range entities {
-// 			c = world.Components[MemWorldCompKey{ctype, id}]
-// 			inqueue <- c
-// 		}
-// 		close(inqueue)
-// 	}
-// }
+// Processes all components of the passed World using their associated
+// processing systems. args will be passed to the System.Process()
+// implementation. This will spawn a separate goroutine per component
+// type that is registered with the World.
+func ProcessParallel(world World, args...[]interface{}) {
+    var wg sync.WaitGroup
+    for _, ctype := range world.ComponentTypes() {
+        wg.Add(1)
+        systems := world.Systems(ctype)
+		go process(&wg, systems, world.Components(ctype), args...)
+    }
+    wg.Wait()
+}
 package ebs
 
-import "testing"
+import (
+    "testing"
+    "math/rand"
+    "strconv"
+	"fmt"
+)
 
-type CompTest1 string
-type CompTest2 string
-type CompTest3 string
-func (c CompTest1) Type() ComponentType {
-	return 1
+var _ = fmt.Printf
+var _ = fmt.Println
+
+const (
+    ENTITYCOUNT = 4000000
+	// Component types
+	MOVEABLE = 1
+	MODIFYABLE = 2
+    TESTABLE = 3
+)
+
+// A simple moveable type. It features a 2D coordinate as well as a
+// velocity for that coordinate.
+type Moveable struct {
+	X float32
+	Y float32
+	VelX float32
+	VelY float32
 }
-func (c CompTest2) Type() ComponentType {
-	return 2
+// The type definition for World implementations and processing systems.
+func (m *Moveable) Type() ComponentType {
+	return MOVEABLE
 }
-func (c CompTest3) Type() ComponentType {
-	return 3
+// Creates a new Moveable component. We are creating pointers here,
+// since we want the processing systems of the World to operate on the
+// components rather than on value copies of them.
+func NewMoveable() *Moveable {
+	return &Moveable{rand.Float32() * 10, rand.Float32() * 10,
+		rand.Float32(), rand.Float32()}
 }
-type InvalidComp string
-
-type TestVector struct {
-	X int
-	Y int
-}
-func NewTestVector(x, y int) *TestVector {
-	return &TestVector{x, y}
-}
-func (c *TestVector) Type() ComponentType {
-	return 55
-}
-
-type TestSystem uint
-func (system TestSystem) ProcessSingle(component Component,
+// A simple processing system, which moves the Moveable by its velocity.
+type MovementSystem int
+func (system *MovementSystem) Process(components []Component,
 	args...[]interface{}) {
-	v := component.(*TestVector)
-	v.X += 1
-	v.Y += 3
-}
-func (system TestSystem) Process(components []Component,
-	args...[]interface{}) {
-	for _, component := range components {
-		system.ProcessSingle(component, args...)
+	for _, c := range components {
+		m := c.(*Moveable)
+        if m.X < 10000 {
+            m.X += m.VelX
+        } else {
+            m.X = 0
+        }
+        if m.Y < 10000 {
+            m.Y += m.VelY
+        } else {
+            m.Y = 0
+        }
 	}
 }
 
-func TestMemWorld(t *testing.T) {
-	world := NewMemWorld()
-	if len(world.ComponentTypes) != 0 {
-		t.Errorf("NewMemWorld() failed")
-	}
-	if len(world.Components) != 0 {
-		t.Errorf("NewMemWorld() failed")
+// A simple modifyable type. It carries a boolean flag indicating, if a change
+// to the object was made
+type Modifyable struct {
+	changed bool
+}
+// The type definition for World implementations and processing systems .
+func (m * Modifyable) Type() ComponentType {
+	return MODIFYABLE
+}
+// A simple processing system, which changes the Modifyable.
+type ModifySystem int
+func (system *ModifySystem) Process(components []Component,
+	args...[]interface{}) {
+	for _, c := range components {
+		m := c.(*Modifyable)
+		m.changed = !m.changed
 	}
 }
 
-func TestMemWorldNewEntity(t *testing.T) {
-	world := NewMemWorld()
-	for i := 1; i < 100; i++ {
-		if world.NewEntity() != Entity(i) {
-			t.Errorf("MemWorld.NewEntity() failed")
-		}
+// A simple testable type.
+type Testable struct {
+	tested string
+}
+// The type definition for World implementations and processing systems .
+func (m * Testable) Type() ComponentType {
+	return TESTABLE
+}
+// A simple processing system, which changes the Testable.
+type TestSystem int
+func (system *TestSystem) Process(components []Component,
+	args...[]interface{}) {
+	for _, c := range components {
+		t := c.(*Testable)
+        pint, err := strconv.ParseInt(t.tested, 10, 0)
+        if err == nil {
+            pint++
+            t.tested = strconv.FormatInt(pint, 10)
+        } else {
+            t.tested = "0"
+        }
 	}
 }
 
-func TestMemWorldAddComponentType(t *testing.T) {
-	typemap := []ComponentType{1, 2, 3}
-	world := NewMemWorld()
-	for _, tp := range typemap {
-		world.AddComponentType(tp)
+func setupTestWorld() *MemWorld {
+    world := NewMemWorld();
+	// Create lots of cars
+	for i := 0; i < ENTITYCOUNT; i++ {
+	 	id := world.NewEntity()
+		move := NewMoveable()
+		mod := &Modifyable{false}
+        ttest := &Testable{"0"}
+		world.Add(id, []Component{move, mod, ttest})
 	}
-	if len(world.ComponentTypes) != len(typemap) {
-		t.Errorf("MemWorld.AddComponentType(): len() mismatch")
-	}
-	for _, key := range typemap {
-		_, ok := world.ComponentTypes[key]
-		if !ok {
-			t.Errorf("%v not in MemWorld.ComponentTypes", key)
-		}
-	}
+	// Enable movement handling
+	world.AddSystem(new(MovementSystem), []ComponentType{MOVEABLE})
+	// Enable modification handling
+	world.AddSystem(new(ModifySystem), []ComponentType{MODIFYABLE})
+	// Enable test handling
+	world.AddSystem(new(TestSystem), []ComponentType{TESTABLE})
+    return world
 }
 
-func TestMemWorldAdd(t *testing.T) {
-	world := NewMemWorld()
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-	c11 := CompTest1("component e11")
-	c12 := CompTest2("component e12")
-	c21 := CompTest1("component e21")
-	c23 := CompTest3("component e23")
-
-	comps1 := []Component{c11, c12}
-	comps2 := []Component{c21, c23}
-
-	world.Add(e1, comps1)
-	world.Add(e2, comps2)
-
-	var ok bool
-
-	for _, comp := range comps1 {
-		_, ok := world.ComponentTypes[comp.Type()]
-		if !ok {
-			t.Errorf("MemWorld.Add() did not set the component type for %v",
-				comp.Type())
-		}
-	}
-
-	// Check entities
-	_, ok = world.ComponentTypes[c11.Type()][e1]
-	if !ok {
-		t.Errorf("MemWorld.Add() did not store %v properly", e1)
-	}
-	_, ok = world.ComponentTypes[c11.Type()][e2]
-	if !ok {
-		t.Errorf("MemWorld.Add() did not store %v properly", e2)
-	}
+// Benchmark the linear processing function
+func BenchmarkProcessLin(b *testing.B) {
+    world := setupTestWorld()
+    b.ResetTimer()
+    for i := 0; i < b.N; i++ {
+        ProcessLinear(world)
+    }
 }
 
-func TestMemWorldDelete(t *testing.T) {
-	world := NewMemWorld()
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-
-	c11 := CompTest1("component e11")
-	c12 := CompTest2("component e12")
-
-	c21 := CompTest1("component e21")
-	c22 := CompTest2("component e22")
-
-	comps1 := []Component{c11, c12}
-	comps2 := []Component{c21, c22}
-
-	world.Add(e1, comps1)
-	world.Add(e2, comps2)
-
-
-	if len(world.Components) != 4 {
-		t.Errorf("inconsistent MemWorld.Add() state")
-	}
-	world.Delete(e1)
-	if len(world.Components) > 2 {
-		t.Errorf("MemWorld.Delete() deleted not enough")
-	}
-	world.Add(e1, comps1)
-	world.Add(e1, comps1)
-	world.Add(e1, comps1)
-	if len(world.Components) != 4 {
-		t.Errorf("inconsistent MemWorld.Add() state")
-	}
-	world.Delete(e1)
-
-	world.Add(e2, comps2)
-	if len(world.Components) > 2 {
-		t.Errorf("MemWorld.Delete() deleted not enough")
-	}
+// Benchmark the parallel processing function
+func BenchmarkProcessPar(b *testing.B) {
+    world := setupTestWorld()
+    b.ResetTimer()
+    for i := 0; i < b.N; i++ {
+        ProcessParallel(world)
+    }
 }
-
-func TestMemWorldGetComponent(t *testing.T) {
-	world := NewMemWorld()
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-
-	c11 := CompTest1("component e11")
-	c12 := CompTest2("component e12")
-
-	c21 := CompTest1("component e21")
-	c23 := CompTest3("component e23")
-
-	comps1 := []Component{c11, c12}
-	comps2 := []Component{c21, c23}
-
-	world.Add(e1, comps1)
-	world.Add(e2, comps2)
-
-	var c Component
-	var ok bool
-
-	c, ok = world.GetComponent(e1, c11.Type())
-	if !ok || c != c11 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, c11, true)
-	}
-	c, ok = world.GetComponent(e1, c12.Type())
-	if !ok || c != c12 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, c12, true)
-	}
-	c, ok = world.GetComponent(e1, c23.Type())
-	if ok || c == c23 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, nil, false)
-	}
-	c, ok = world.GetComponent(e2, c21.Type())
-	if !ok || c != c21 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, c21, true)
-	}
-	c, ok = world.GetComponent(e2, c23.Type())
-	if !ok || c != c23 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, c23, true)
-	}
-	c, ok = world.GetComponent(e2, c12.Type())
-	if ok || c == c12 {
-		t.Errorf("MemWorld.GetComponent() returns (%v, %v), expected (%v, %v)",
-			c, ok, nil, false)
-	}
-}
-
-func TestMemWorldSetComponent(t *testing.T) {
-	world := NewMemWorld()
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-	e3 := world.NewEntity()
-
-	c11 := CompTest1("component e11")
-	c12 := CompTest2("component e12")
-
-	c21 := CompTest1("component e21")
-	c23 := CompTest3("component e23")
-
-	comps1 := []Component{c11, c12}
-	comps2 := []Component{c21, c23}
-
-	world.Add(e1, comps1)
-	world.Add(e2, comps2)
-
-	var ok bool
-
-	world.SetComponent(e1, c21)
-	_, ok = world.ComponentTypes[c21.Type()][e1]
-	if !ok {
-		t.Errorf("MemWorld.SetComponent(%v, %v) did not work", e1, c21)
-	}
-	_, ok = world.ComponentTypes[c11.Type()][e1]
-	if !ok {
-		t.Errorf("MemWorld.SetComponent() did not store the component")
-	}
-	_, ok = world.ComponentTypes[c21.Type()][e3]
-	if ok {
-		t.Errorf("MemWorld.SetComponent() should not store the component")
-	}
-}
-
-func TestMemWorldDeleteComponent(t *testing.T) {
-	world := NewMemWorld()
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-
-	c11 := CompTest1("component e11")
-	c12 := CompTest2("component e12")
-
-	c21 := CompTest1("component e21")
-	c23 := CompTest3("component e23")
-
-	comps1 := []Component{c11, c12}
-	comps2 := []Component{c21, c23}
-
-	world.Add(e1, comps1)
-	world.Add(e2, comps2)
-
-	var c Component
-	var ok bool
-
-	world.DeleteComponent(e1, c11.Type())
-	c, ok = world.GetComponent(e1, c11.Type())
-	if ok || c == c11 {
-		t.Errorf("MemWorld.DeleteComponent() did not work")
-	}
-	c, ok = world.GetComponent(e2, c11.Type())
-	if !ok || c != c21 {
-		t.Errorf("MemWorld.DeleteComponent() deleted too much")
-	}
-}
-
-func TestMemWorldAddSystem(t *testing.T) {
-	world := NewMemWorld()
-	s1 := TestSystem(1)
-	s2 := TestSystem(2)
-	ct1 := []ComponentType{1,}
-	ct2 := []ComponentType{3,}
-
-	world.AddSystem(s1, ct1)
-	if len(world.Systems) != 1 {
-		t.Errorf("MemWorld.AddSystem(%v) did not work", s1)
-	}
-	world.AddSystem(s1, ct1)
-	if len(world.Systems) != 1 {
-		t.Errorf("MemWorld.AddSystem(%v) added duplicate", s1)
-	}
-	world.AddSystem(s2, ct2)
-	if len(world.Systems) != 2 {
-		t.Errorf("MemWorld.AddSystem(%v) added duplicate", s2)
-	}
-	if world.Systems[ct1[0]][0] != s1 {
-		t.Errorf("MemWorld.AddSystem() messed up the addition order (1)")
-	}
-	if world.Systems[ct2[0]][0]!= s2 {
-		t.Errorf("MemWorld.AddSystem() messed up the addition order (2)")
-	}
-}
-
-func TestMemWorldRemoveSystem(t *testing.T) {
-	world := NewMemWorld()
-	s1 := TestSystem(1)
-	s2 := TestSystem(2)
-	ct1 := []ComponentType{1,}
-	ct2 := []ComponentType{3,}
-
-	world.AddSystem(s1, ct1)
-	world.RemoveSystem(s1)
-	if len(world.Systems[ct1[0]]) != 0 {
-		t.Errorf("MemWorld.RemoveSystem(%v) did not work", s1)
-	}
-	world.AddSystem(s1, ct1)
-	world.AddSystem(s2, ct2)
-	world.RemoveSystem(s2)
-	if len(world.Systems[ct1[0]]) != 1 && len(world.Systems[ct2[0]]) != 0{
-		t.Errorf("MemWorld.RemoveSystem(%v) did not work properly", s2)
-	}
-	if world.Systems[ct1[0]][0] != s1 {
-		t.Errorf("MemWorld.RemoveSystem(%v) removed the wrong System", s2)
-	}
-}
-
-func TestMemWorldProcess(t *testing.T) {
-	world := NewMemWorld()
-	system := TestSystem(1)
-	c1 := TestVector{0, 0}
-	c2 := TestVector{10, 5}
-	c3 := TestVector{-20, -18}
-	c4 := TestVector{55, -33}
-	c5 := TestVector{4, 4}
-	e1 := world.NewEntity()
-	e2 := world.NewEntity()
-	e3 := world.NewEntity()
-	e4 := world.NewEntity()
-	e5 := world.NewEntity()
-	world.Add(e1, []Component{&c1,})
-	world.Add(e2, []Component{&c2,})
-	world.Add(e3, []Component{&c3,})
-	world.Add(e4, []Component{&c4,})
-	world.Add(e5, []Component{&c5,})
-	world.AddSystem(system, []ComponentType{c1.Type(),})
-	world.Process()
-	if c1.X != 1 && c1.Y != 3 {
-		t.Errorf("MemWorld.Process() did not modify the values in place (1)")
-	}
-	if c4.X != 56 && c4.Y != -30 {
-		t.Errorf("MemWorld.Process() did not modify the values in place (2)")
-	}
-	world.Process()
-	if c1.X != 4 && c1.Y != 6 {
-		t.Errorf("MemWorld.Process() did not modify the values in place (3)")
-	}
-	if c4.X != 59 && c4.Y != -27 {
-		t.Errorf("MemWorld.Process() did not modify the values in place (4)")
-	}
-}

ebs/example_test.go

-package ebs
-
-import (
-	"fmt"
-//	"time"
-	"math/rand"
-)
-
-// Constants
-const (
-	ECOUNT = 10000
-	// Component types
-	MOVEABLE = 1
-	MODIFYABLE = 2
-
-)
-
-// A simple moveable type. It features a 2D coordinate as well as a
-// velocity for that coordinate.
-type Moveable struct {
-	X float32
-	Y float32
-	VelX float32
-	VelY float32
-}
-// The type definition for World implementations and processing systems.
-func (m *Moveable) Type() ComponentType {
-	return MOVEABLE
-}
-// Creates a new Moveable component. We are creating pointers here,
-// since we want the processing systems of the World to operate on the
-// components rather than on value copies of them.
-func NewMoveable() *Moveable {
-	return &Moveable{rand.Float32() * 10, rand.Float32() * 10,
-		rand.Float32(), rand.Float32()}
-}
-// A simple processing system, which moves the Moveable by its velocity.
-type MovementSystem int
-func (system *MovementSystem) Process(components []Component,
-	args...[]interface{}) {
-	for _, c := range components {
-		m := c.(*Moveable)
-		m.X += m.VelX
-		m.Y += m.VelY
-	}
-}
-func (system *MovementSystem) ProcessSingle(component Component,
-	args...[]interface{}) {
-	m := component.(*Moveable)
-	m.X += m.VelX
-	m.Y += m.VelY
-}
-
-type Modifyable struct {
-	changed bool
-}
-func (m * Modifyable) Type() ComponentType {
-	return MODIFYABLE
-}
-func NewModifyable() *Modifyable {
-	return &Modifyable{false}
-}
-// A simple processing system, which moves the Moveable by its velocity.
-type ModifySystem int
-func (system *ModifySystem) Process(components []Component,
-	args...[]interface{}) {
-	for _, c := range components {
-		m := c.(*Modifyable)
-		m.changed = true
-	}
-}
-func (system *ModifySystem) ProcessSingle(component Component,
-	args...[]interface{}) {
-	m := component.(*Modifyable)
-	m.changed = true
-}
-
-func Example() {
-	world := NewMemWorld()
-
-	// Create lots of cars
-	for i := 0; i < ECOUNT; i++ {
-	 	id := world.NewEntity()
-		move := NewMoveable()
-		mod := NewModifyable()
-		world.Add(id, []Component{move, mod})
-	}
-
-	// Enable the car movement
-	system := new(MovementSystem)
-	world.AddSystem(system, []ComponentType{MOVEABLE})
-
-	//parstart := time.Now()
-	world.Process()
-	//parduration := time.Since(parstart)
-	//fmt.Printf("par: %v\n", parduration)
-
-	fmt.Println("hello")
-	// Output:
-	// hello
-}