1 /**
2 Entity management module.
3 
4 Copyright: © 2015-2016 Claude Merle
5 Authors: Claude Merle
6 License: This file is part of EntitySysD.
7 
8 EntitySysD is free software: you can redistribute it and/or modify it
9 under the terms of the Lesser GNU General Public License as published
10 by the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 EntitySysD is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 Lesser GNU General Public License for more details.
17 
18 You should have received a copy of the Lesser GNU General Public License
19 along with EntitySysD. If not, see $(LINK http://www.gnu.org/licenses/).
20 */
21 
22 module entitysysd.entity;
23 
24 import std.bitmanip;
25 import std.container;
26 import std.string;
27 
28 import entitysysd.component;
29 import entitysysd.event;
30 import entitysysd.exception;
31 import entitysysd.pool;
32 
33 /// Attribute to use uppon component struct's and union's.
34 public import entitysysd.component : component;
35 
36 /**
37  * Entity structure.
38  *
39  * This is the combination of two 32-bits id: a unique-id and a version-id.
40  */
41 struct Entity
42 {
43 public:
44     static struct Id
45     {
46     public:
47         this(uint uId, uint vId)
48         {
49             mId = cast(ulong)uId | cast(ulong)vId << 32;
50         }
51 
52         ulong id() const @property
53         {
54             return mId;
55         }
56         uint uniqueId() @property
57         {
58             return mId & 0xffffffffUL;
59         }
60         uint versionId() @property
61         {
62             return mId >> 32;
63         }
64 
65         bool opEquals()(auto const ref Id lId) const
66         {
67             return id == lId.id;
68         }
69 
70         string toString()
71         {
72             return format("#%d:%d", uniqueId, versionId);
73         }
74 
75     private:
76         ulong   mId;
77     }
78 
79     enum Id invalid = Id(0, 0);
80 
81     this(EntityManager manager, Id id)
82     {
83         mManager = manager;
84         mId = id;
85     }
86 
87     /**
88      * Destroy the entity (unregister all attached components).
89      *
90      * Throws: EntityException if the entity is invalid.
91      */
92     void destroy()
93     {
94         enforce!EntityException(valid);
95         mManager.destroy(mId);
96         invalidate();
97     }
98 
99     /**
100      * Tells whether the entity is valid.
101      *
102      * Returns: true if the entity is valid, false otherwise.
103      */
104     bool valid() @property
105     {
106         return mManager !is null && mManager.valid(mId);
107     }
108 
109     /**
110      * Invalidate the entity instance (but does not destroy it).
111      */
112     void invalidate()
113     {
114         mId = invalid;
115         mManager = null;
116     }
117 
118     /**
119      * Returns the id of the entity.
120      */
121     Id id() const @property
122     {
123         return mId;
124     }
125 
126     /**
127      * Register a component C to an entity.
128      *
129      * Params:
130      *   C    = Component to register.
131      *   args = List of arguments to initialize the component, will be passed to
132      *          its constructor. Optional.
133      *
134      * Returns: A pointer on the component for this entity.
135      *
136      * Throws: $(D EntityException) if the entity is invalid.
137      *         $(D ComponentException) if there is no room for that component or
138      *                                 if the component is already registered.
139      */
140     C* register(C, Args...)(Args args)
141         if (isComponent!C)
142     {
143         enforce!EntityException(valid);
144         auto component = mManager.register!C(mId);
145         static if (Args.length != 0)
146             *component = C(args);
147         return component;
148     }
149 
150     /**
151      * Unregister a component C from an entity.
152      *
153      * Params:
154      *   C = Component to unregister.
155      *
156      * Throws: $(D EntityException) if the entity is invalid.
157      *         $(D ComponentException) if the component is not registered.
158      */
159     void unregister(C)()
160         if (isComponent!C)
161     {
162         enforce!EntityException(valid);
163         mManager.unregister!C(mId);
164     }
165 
166     /**
167      * Get a component pointer of the entity.
168      *
169      * Params:
170      *   C = Component for the entity.
171      *
172      * Returns: A pointer on the component for this entity.
173      *
174      * Throws: $(D EntityException) if the entity is invalid.
175      *         $(D ComponentException) if the component is not registered.
176      */
177     C* component(C)() @property
178         if (isComponent!C)
179     {
180         enforce!EntityException(valid);
181         return mManager.getComponent!(C)(mId);
182     }
183 
184     /**
185      * Set the value of a component of the entity.
186      *
187      * Params:
188      *   C = Component to set.
189      *
190      * Throws: $(D EntityException) if the entity is invalid.
191      *         $(D ComponentException) if the component is not registered.
192      */
193     void component(C)(auto ref C c) @property
194         if (isComponent!C)
195     {
196         enforce!EntityException(valid);
197         *mManager.getComponent!(C)(mId) = c;
198     }
199 
200     /**
201      * Tell whether a component is registered to the entity.
202      *
203      * Params:
204      *   C = Component to test.
205      *
206      * Returns: $(D true) if the component is registered to the entity,
207      *          $(D false) otherwise.
208      *
209      * Throws: EntityException if the entity is invalid.
210      */
211     bool isRegistered(C)()
212         if (isComponent!C)
213     {
214         enforce!EntityException(valid);
215         return mManager.isRegistered!C(mId);
216     }
217 
218     /**
219      * Iterate over the components registered to the entity. It calls the
220      * accessor delegate that has been set to each component.
221      *
222      * Throws: $(D EntityException) if the entity is invalid.
223      */
224     void iterate()
225     {
226         enforce!EntityException(valid);
227         mManager.iterate(this);
228     }
229 
230     /**
231      * Compare two entities and tells whether they are the same (same id).
232      */
233     bool opEquals()(auto const ref Entity e) const
234     {
235         return id == e.id;
236     }
237 
238     /**
239      * Returns a string representation of an entity.
240      *
241      * It has the form: #uid:vid where uid is the unique-id and
242      * vid is the version-id
243      */
244     string toString()
245     {
246         return mId.toString();
247     }
248 
249 private:
250     EntityManager mManager;
251     Id            mId = invalid;
252 }
253 
254 ///
255 unittest
256 {
257     @component struct Position
258     {
259         float x, y;
260     }
261 
262     auto em = new EntityManager(new EventManager);
263     auto entity = em.create();
264     auto posCompPtr = entity.register!Position(2.0, 3.0);
265 
266     assert(posCompPtr == entity.component!Position);
267     assert(posCompPtr.x == 2.0);
268     assert(entity.component!Position.y == 3.0);
269 }
270 
271 /**
272  * Manages entities creation and component memory management.
273  */
274 class EntityManager
275 {
276 public:
277     /**
278      * Constructor of the entity-manager.
279      * Params:
280      *   eventManager = May be used to notify about entity creation and
281      *                  component registration.
282      *   maxComponent = Maximum number of components supported by the whole
283      *                  manager.
284      *   poolSize     = Chunk size in bytes for each components.
285      */
286     this(EventManager eventManager,
287          size_t maxComponent = 64,
288          size_t poolSize     = 8192)
289     {
290         mEventManager = eventManager;
291         mMaxComponent = maxComponent;
292         mPoolSize     = poolSize;
293     }
294 
295     /**
296      * Current number of managed entities.
297      */
298     size_t size() @property
299     {
300         return mEntityComponentMask.length - mNbFreeIds;
301     }
302 
303     /**
304      * Current capacity entity.
305      */
306     size_t capacity() @property
307     {
308         return mEntityComponentMask.length;
309     }
310 
311     /**
312      * Return true if the given entity ID is still valid.
313      */
314     bool valid(Entity.Id id)
315     {
316         return id != Entity.invalid &&
317                id.uniqueId-1 < mEntityVersions.length &&
318                mEntityVersions[id.uniqueId-1] == id.versionId;
319     }
320 
321     /**
322      * Create an entity.
323      *
324      * Returns: a new valid entity.
325      */
326     Entity create()
327     {
328         uint uniqueId, versionId;
329 
330         if (mFreeIds.empty)
331         {
332             mIndexCounter++;
333             uniqueId = mIndexCounter;
334             accomodateEntity();
335             versionId = mEntityVersions[uniqueId-1];
336         }
337         else
338         {
339             uniqueId = mFreeIds.front;
340             mFreeIds.removeFront();
341             mNbFreeIds--;
342             versionId = mEntityVersions[uniqueId-1];
343         }
344 
345         Entity entity = Entity(this, Entity.Id(uniqueId, versionId));
346 
347         return entity;
348     }
349 
350     /**
351      * Returns an entity from an an entity-id
352      *
353      * Returns: the entity from the id.
354      *
355      * Throws: EntityException if the id is invalid.
356      */
357     Entity getEntity(Entity.Id id)
358     {
359         enforce!EntityException(valid(id));
360         return Entity(this, id);
361     }
362 
363     //*** Browsing features ***
364 
365     /**
366      * Allows to browse through all the valid entities of the manager with
367      * a foreach loop.
368      *
369      * Examples:
370      * --------------------
371      * foreach (entity; entityManager)
372      * { ... }
373      * --------------------
374      */
375     int opApply(int delegate(Entity entity) dg)
376     {
377         int result = 0;
378 
379         // copy version-ids
380         auto versionIds = mEntityVersions.dup;
381         // and remove those that are free
382         foreach (freeId; mFreeIds)
383             versionIds[freeId-1] = uint.max;
384 
385         foreach (uniqueId, versionId; versionIds)
386         {
387             if (versionId == uint.max)
388                 continue;
389             result = dg(Entity(this,
390                                Entity.Id(cast(uint)uniqueId+1, versionId)));
391             if (result)
392                 break;
393         }
394 
395         return result;
396     }
397 
398 
399     /**
400      * Return a range of all the valid instances of a component.
401      */
402     auto components(C)() @property
403         if (isComponent!C)
404     {
405         import std.range : iota;
406         import std.algorithm : map, filter;
407 
408         immutable compId = componentId!C();
409 
410         // if no such component has ever been registered, no pool will exist.
411         auto pool = cast(Pool!C)mComponentPools[compId];
412         assert(pool !is null, "A component pool should never be null");
413 
414         return iota(0, pool.nbElements)
415             .filter!(i => mEntityComponentMask[i][compId])
416             .map!(i => &pool[i]);
417     }
418 
419     /**
420      * Allows to browse through the entities that have a required set of
421      * components.
422      *
423      * Examples:
424      * --------------------
425      * foreach (entity; entityManager.entitiesWith!(CompA, CompB))
426      * { ... }
427      * --------------------
428      */
429     auto entitiesWith(CList...)() @property
430         if (areComponents!CList)
431     {
432         struct EntitiesWithView(CList...)
433             if (areComponents!CList)
434         {
435             this(EntityManager em)
436             {
437                 entityManager = em;
438             }
439 
440             int opApply(int delegate(Entity entity) dg)
441             {
442                 int result = 0;
443 
444                 entityLoop: foreach (i, ref componentMask;
445                                      entityManager.mEntityComponentMask)
446                 {
447                     foreach (C; CList)
448                     {
449                         auto compId = entityManager.componentId!C();
450                         if (!componentMask[compId])
451                             continue entityLoop;
452                     }
453 
454                     auto versionId = entityManager.mEntityVersions[i];
455                     result = dg(Entity(entityManager,
456                                        Entity.Id(cast(uint)i+1, versionId)));
457                     if (result)
458                         break;
459                 }
460 
461                 return result;
462             }
463 
464             int opApply(int delegate(Entity entity, Pointers!CList components) dg)
465             {
466                 auto withComponents(Entity ent)
467                 {
468                     auto get(T)()
469                     {
470                         return ent.component!T;
471                     }
472                     import std.meta : staticMap;
473                     return dg(ent, staticMap!(get, CList));
474                 }
475 
476                 return opApply(&withComponents);
477             }
478 
479             EntityManager entityManager;
480         }
481         return EntitiesWithView!(CList)(this);
482     }
483 
484     alias CompAccessor = void delegate(Entity e, void* pc);
485 
486     /**
487      * Set an accessor delegate for a component.
488      *
489      * Params:
490      *   C  = Component to which the accessor delegate will be set.
491      *   dg = Delegate that will be called when using $(D Entity.iterate).
492      *        Use $(D null) to clear the accessor.
493      */
494     void accessor(C)(void delegate(Entity e, C* pc) dg) @property
495     {
496         immutable compId = ComponentCounter!(C).getId();
497         // Make sure the delegate array is large enough
498         if (mComponentAccessors.length <= compId)
499         {
500             if (dg is null)
501                 return;
502             else
503                 mComponentAccessors.length = compId + 1;
504         }
505         mComponentAccessors[compId] = cast(CompAccessor)dg;
506     }
507 
508     /**
509      * Get the accessor delegate assigned to a component.
510      *
511      * Params:
512      *   C  = Component from which the accessor delegate will be retreived.
513      *
514      * Returns:
515      *   The accessor delegate; null if it has never been set, if it was cleared
516      *   or if the component is missing.
517      */
518     void delegate(Entity e, C* pc) accessor(C)() @property
519     {
520         immutable compId = ComponentCounter!(C).getId();
521         if (mComponentAccessors.length <= compId)
522             return null;
523         return cast(void delegate(Entity e, C* pc))mComponentAccessors[compId];
524     }
525 
526 private:
527     void destroy(Entity.Id id)
528     {
529         uint uniqueId = id.uniqueId;
530 
531         // reset all components for that entity
532         foreach (ref bit; mEntityComponentMask[uniqueId-1])
533             bit = 0;
534         // invalidate its version, incrementing it
535         mEntityVersions[uniqueId-1]++;
536         mFreeIds.insertFront(uniqueId);
537         mNbFreeIds++;
538     }
539 
540     C* register(C)(Entity.Id id)
541         if (isComponent!C)
542     {
543         const auto compId = componentId!(C)();
544         enforce!ComponentException(compId < mMaxComponent);
545         const auto uniqueId = id.uniqueId;
546         enforce!ComponentException(!mEntityComponentMask[uniqueId-1][compId]);
547 
548         // place new component into the pools
549         auto pool = cast(Pool!C)mComponentPools[compId];
550         assert(pool !is null, "A component pool should never be null");
551 
552         // Set the bit for this component.
553         mEntityComponentMask[uniqueId-1][compId] = true;
554 
555         pool.initN(uniqueId-1);
556 
557         return &pool[uniqueId-1];
558     }
559 
560     void unregister(C)(Entity.Id id)
561         if (isComponent!C)
562     {
563         const auto compId = componentId!(C)();
564         enforce!ComponentException(compId < mMaxComponent);
565         const auto uniqueId = id.uniqueId;
566         enforce!ComponentException(mEntityComponentMask[uniqueId-1][compId]);
567 
568         // Remove component bit.
569         mEntityComponentMask[uniqueId-1][compId] = false;
570     }
571 
572     bool isRegistered(C)(Entity.Id id)
573         if (isComponent!C)
574     {
575         const auto compId = componentId!(C)();
576         const auto uniqueId = id.uniqueId;
577 
578         if (compId >= mMaxComponent)
579             return false;
580 
581         return mEntityComponentMask[uniqueId-1][compId];
582     }
583 
584     C* getComponent(C)(Entity.Id id)
585         if (isComponent!C)
586     {
587         const auto compId = componentId!(C)();
588         enforce!ComponentException(compId < mMaxComponent);
589         const auto uniqueId = id.uniqueId;
590         enforce!ComponentException(mEntityComponentMask[uniqueId-1][compId]);
591 
592         // Placement new into the component pool.
593         Pool!C pool = cast(Pool!C)mComponentPools[compId];
594         return &pool[uniqueId-1];
595     }
596 
597     size_t componentId(C)()
598     {
599         immutable compId = ComponentCounter!(C).getId();
600 
601         // ensure we have a pool to hold components of this type
602         if (mComponentPools.length <= compId)
603         {
604             mComponentPools.length = compId + 1;
605             mComponentPools[compId] = new Pool!C(mIndexCounter);
606         }
607 
608         return compId;
609     }
610 
611     void accomodateEntity()
612     {
613         if (mEntityComponentMask.length < mIndexCounter)
614         {
615             mEntityComponentMask.length = mIndexCounter;
616             foreach (ref mask; mEntityComponentMask)
617                 mask.length = mMaxComponent;
618             mEntityVersions.length = mIndexCounter;
619             foreach (ref pool; mComponentPools)
620                 pool.accomodate(mIndexCounter);
621         }
622     }
623 
624     void iterate(Entity entity)
625     {
626         const auto uniqueId = entity.id.uniqueId;
627 
628         // Iterate over all components registered to that entity
629         foreach (compId; 0..mComponentAccessors.length)
630         {
631             // If the component is registered and has a delegate
632             if (mEntityComponentMask[uniqueId-1][compId])
633                 if (mComponentAccessors[compId] !is null)
634                 {
635                     auto compPtr = mComponentPools[compId].getPtr(uniqueId-1);
636                     mComponentAccessors[compId](entity, compPtr);
637                 }
638         }
639     }
640 
641     // Current number of Entities
642     uint            mIndexCounter = 0;
643     size_t          mMaxComponent;
644     size_t          mPoolSize;
645     // Event Manager
646     EventManager    mEventManager;
647     // Array of pools for each component types
648     BasePool[]      mComponentPools;
649     // Bitmask of components for each entities
650     // Index into the vector is the Entity.Id
651     BitArray[]      mEntityComponentMask;
652     // Array of delegates for each component
653     CompAccessor[]  mComponentAccessors;
654     // Vector of entity version id's
655     // Incremented each time an entity is destroyed
656     uint[]          mEntityVersions;
657     // List of available entity id's.
658     SList!uint      mFreeIds;
659     uint            mNbFreeIds;
660 }
661 
662 // Translate a list of types to a list of pointers to those types.
663 private template Pointers(T...)
664 {
665     import std.meta : staticMap;
666     private alias PtrTo(U) = U*;
667     alias Pointers = staticMap!(PtrTo, T);
668 }
669 
670 
671 //******************************************************************************
672 //***** UNIT-TESTS
673 //******************************************************************************
674 
675 import std.stdio;
676 
677 unittest
678 {
679     auto em = new EntityManager(new EventManager());
680 
681     auto ent0 = em.create();
682     assert(em.capacity == 1);
683     assert(em.size == 1);
684     assert(ent0.valid);
685     assert(ent0.id.uniqueId == 1);
686     assert(ent0.id.versionId == 0);
687 
688     ent0.destroy();
689     assert(em.capacity == 1);
690     assert(em.size == 0);
691     assert(!ent0.valid);
692     assert(ent0.id.uniqueId == 0);
693     assert(ent0.id.versionId == 0);
694 
695     ent0 = em.create();
696     auto ent1 = em.create();
697     auto ent2 = em.create();
698     assert(em.capacity == 3);
699     assert(em.size == 3);
700     assert(ent0.id.uniqueId == 1);
701     assert(ent0.id.versionId == 1);
702     assert(ent1.id.uniqueId == 2);
703     assert(ent1.id.versionId == 0);
704     assert(ent2.id.uniqueId == 3);
705     assert(ent2.id.versionId == 0);
706 
707     @component struct NameComponent
708     {
709         string name;
710     }
711 
712     @component struct PosComponent
713     {
714         int x, y;
715     }
716     ent0.register!NameComponent();
717     ent1.register!NameComponent();
718     ent2.register!NameComponent();
719 
720     ent0.register!PosComponent();
721     ent2.register!PosComponent();
722 
723     ent0.component!NameComponent.name = "Hello";
724     ent1.component!NameComponent.name = "World";
725     ent2.component!NameComponent.name = "Again";
726     assert(ent0.component!NameComponent.name == "Hello");
727     assert(ent1.component!NameComponent.name == "World");
728     assert(ent2.component!NameComponent.name == "Again");
729 
730     ent0.component!PosComponent = PosComponent(5, 6);
731     ent2.component!PosComponent = PosComponent(2, 3);
732     assert(ent0.component!PosComponent.x == 5);
733     assert(ent0.component!PosComponent.y == 6);
734     assert(ent2.component!PosComponent.x == 2);
735     assert(ent2.component!PosComponent.y == 3);
736 
737     //ent1.destroy();
738 
739     // List all current valid entities
740     foreach (ent; em)
741     {
742         assert(ent.valid);
743         //writeln(ent.component!NameComponent.name);
744     }
745 
746     // List all name components
747     foreach (comp; em.components!NameComponent)
748     {
749         //writeln(comp.name);
750     }
751 
752     // List all name components
753     foreach (ent; em.entitiesWith!(NameComponent, PosComponent))
754     {
755         assert(ent.valid);
756         //writeln(ent.component!NameComponent.name);
757     }
758 
759     // Check const fields are properly handled
760     @component struct ConstComp
761     {
762         int           a, b;
763         const float   cFloat = 5.0;
764         immutable int iInt = 5;
765     }
766 
767     ent0.register!ConstComp();
768     assert(ent0.component!ConstComp.cFloat == 5.0);
769 
770     // Check immutable fields are not accepted
771     @component struct ImmutableComp
772     {
773         int             a, b;
774         shared    float sFloat = 5.0;
775         __gshared float gsFloat = 5.0;
776     }
777 
778     // Check it will NOT compile if a field is shared
779     assert(!__traits(compiles, ent0.register!ImmutableComp()));
780 }
781 
782 unittest
783 {
784     @component struct Velocity { int x, y; }
785     @component struct Position { int x, y; }
786 
787     auto em = new EntityManager(new EventManager());
788 
789     auto ent0 = em.create();
790     auto ent1 = em.create();
791 
792     ent0.register!Position(0, 0);
793     ent1.register!Position(4, 5);
794 
795     ent0.register!Velocity(1, 2);
796     ent1.register!Velocity(3, 4);
797 
798     // test getting components from the opApply loop
799     foreach(ent, pos, vel; em.entitiesWith!(Position, Velocity))
800     {
801         pos.x += vel.x;
802         pos.y += vel.y;
803     }
804 
805     assert(ent0.component!Position.x == 1 && ent0.component!Position.y == 2);
806     assert(ent1.component!Position.x == 7 && ent1.component!Position.y == 9);
807 }
808 
809 // Ensure that em.components!T does not throw if no `T` has ever been registered
810 unittest
811 {
812     @component struct Dummy { }
813 
814     auto em = new EntityManager(new EventManager());
815 
816     foreach(pos ; em.components!Dummy)
817         assert(0, "Loop should never be entered");
818 }
819 
820 // Validate fix for a bug where you could end up with uninitialized pools.
821 // ent.isRegistered would create room for a pool without allocating it,
822 // potentially creating null pools in the middle of the collection.
823 // register was only checking the collection length, but did not ensure that the
824 // pool it retrieved to store the component was non-null.
825 unittest
826 {
827     @component struct Dummy1 { }
828     @component struct Dummy2 { }
829 
830     auto em = new EntityManager(new EventManager());
831     auto ent = em.create();
832 
833     assert(!ent.isRegistered!Dummy1);
834     assert(!ent.isRegistered!Dummy2);
835     assert(ent.register!Dummy2);
836     assert(ent.register!Dummy1);
837 }
838 
839 // Test range interface for components!T
840 unittest
841 {
842     @component struct A
843     {
844         int a;
845     }
846 
847     @component struct B
848     {
849         string b;
850     }
851 
852     auto em = new EntityManager(new EventManager());
853 
854     auto e1 = em.create();
855     auto e2 = em.create();
856     auto e3 = em.create();
857 
858     e1.register!A(1);
859     e2.register!B("2");
860     e3.register!A(3);
861     e3.register!B("3");
862 
863     import std.algorithm : map, equal;
864     assert(em.components!A.map!(x => x.a).equal([1, 3]));
865     assert(em.components!B.map!(x => x.b).equal(["2", "3"]));
866 }
867 
868 
869 // Test component accessors
870 unittest
871 {
872     import std.conv;
873     string output;
874 
875     @component struct A
876     {
877         int i;
878     }
879 
880     @component struct B
881     {
882         string str;
883     }
884 
885     auto em = new EntityManager(new EventManager());
886 
887     auto e1 = em.create();
888     auto e2 = em.create();
889     auto e3 = em.create();
890 
891     e1.register!A(1);
892     e2.register!B("hello");
893     e3.register!A(3);
894     e3.register!B("world");
895 
896     void accessorForA(Entity e, A* a)
897     {
898         assert(e == e1 || e == e3);
899         output ~= a.i.to!string;
900     }
901 
902     em.accessor!A = &accessorForA;
903     assert(em.accessor!A == &accessorForA);
904     em.accessor!B = (e, b) { output ~= b.str; }; // use lambda
905 
906     e1.iterate();
907     assert(output == "1");
908 
909     output = "";
910     e2.iterate();
911     assert(output == "hello");
912 
913     output = "";
914     e3.iterate();
915     assert(output == "3world");
916 }