diff --git a/.gitignore b/.gitignore index 86d89f8..822a65c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ ignore/ *.obj *.cam *.tar.gz +*.Identifier callgrind.* # Images diff --git a/ecs2.h b/ecs2.h index e11c45e..6a78a3b 100644 --- a/ecs2.h +++ b/ecs2.h @@ -11,41 +11,64 @@ #define ECS_MAXENTITIES 1024 #endif -#define ECS_MAXCTYPES 63 // uint64 bits minus one +// We reserve one slot to automatically point back to the ecs system. +// This is the unusable 64th ID = 63 (your ids should start from 0) +#define ECS_MAXCTYPES 63 +// The self flag is an ID that will get you back a component that is +// the ecs system itself. It is ALSO used to identify is an entity is +// valid, as ALL entities will implicitly have the ECS component +#define ECS_SELFFLAG (1ULL << ECS_MAXCTYPES) typedef unsigned long long ecs_cid; typedef int ecs_eid; #define ECS_START(name) \ - typedef struct { \ + typedef struct name name; \ + struct name { \ ecs_cid entities[ECS_MAXENTITIES]; \ - ecs_eid entitytop; + ecs_eid entitytop; \ + name *c_##name[ECS_MAXENTITIES]; #define ECS_END(name) \ } \ - name; \ + ; \ + /* Always initialize the ecs system when you create a new one! */ \ static void name##_init(name *_ecs) { memset(_ecs, 0, sizeof(name)); } \ + /* Create an entity with the given base components (usually 0) */ \ static ecs_eid name##_newentity(name *_ecs, ecs_cid basecomponents) { \ for (int i = 0; i < ECS_MAXENTITIES; i++) { \ - ecs_eid id = _ecs->entitytop++; \ + ecs_eid id = _ecs->entitytop; \ + _ecs->entitytop = (_ecs->entitytop + 1) % ECS_MAXENTITIES; \ if (_ecs->entities[id] == 0) { \ - _ecs->entities[id] = (1ULL << ECS_MAXCTYPES) | basecomponents; \ + _ecs->entities[id] = ECS_SELFFLAG | basecomponents; \ + _ecs->c_##name[id] = _ecs; \ return id; \ } \ } \ return -1; \ } \ + /* Delete an entity by eid from the given ecs sys */ \ static void name##_deleteentity(name *_ecs, ecs_eid eid) { \ if (eid >= 0 && eid < ECS_MAXENTITIES) \ _ecs->entities[eid] = 0; \ } \ + /* Whether an entity matches a given list of components by flag */ \ static int name##_match(name *_ecs, ecs_eid _eid, ecs_cid _comps) { \ - ecs_cid _realcomps = (1ULL << ECS_MAXCTYPES) | _comps; \ + ecs_cid _realcomps = ECS_SELFFLAG | _comps; \ return (_ecs->entities[_eid] & _realcomps) == _realcomps; \ - } + } \ + /* Calculate the eid from a double ecs pointer. Useful to get eid in sys */ \ + static ecs_eid name##_eid(name **_ecs) { \ + return (ecs_eid)(_ecs - (*_ecs)->c_##name); \ + } \ + const ecs_cid name##_fl = ECS_SELFFLAG; +// Create an ECS component within an ECS struct #define ECS_COMPONENT(type) type c_##type[ECS_MAXENTITIES]; +// Define the CIDs necessary to access a component (each component MUST +// have a unique id and I can't do that inside a macro without requiring +// extensions) #define ECS_CID(type, id) \ const int type##_id = id; \ const ecs_cid type##_fl = (1ULL << id); @@ -116,4 +139,18 @@ typedef int ecs_eid; } \ } +// Add a system function which automatically calls your given function with +// pre-pulled items from the entity component arrays. The new function is +// named the same as the old one, just with _run appeneded +#define ECS_SYSTEM6(ecsname, fname, type1, type2, type3, type4, type5, type6) \ + void fname##_run(ecsname *_ecs, ecs_eid eid) { \ + ecs_cid _ecsflags = type1##_fl | type2##_fl | type3##_fl | type4##_fl | \ + type5##_fl | type6##_fl; \ + if (ecsname##_match(_ecs, eid, _ecsflags)) { \ + fname(_ecs->c_##type1 + eid, _ecs->c_##type2 + eid, \ + _ecs->c_##type3 + eid, _ecs->c_##type4 + eid, \ + _ecs->c_##type5 + eid, _ecs->c_##type6 + eid); \ + } \ + } + #endif diff --git a/haloo3d b/haloo3d index 8d814bd..96dbee2 160000 --- a/haloo3d +++ b/haloo3d @@ -1 +1 @@ -Subproject commit 8d814bd4abae2fb0113e5675f838ed2caa4e938f +Subproject commit 96dbee2942ae8b3d09302a24b075024c8134bb55 diff --git a/maze.c b/maze.c index d809696..e6ceb94 100644 --- a/maze.c +++ b/maze.c @@ -9,8 +9,11 @@ #include "unigi/unigi.headers/src/main.h" #include "unigi/unigi.platform.sdl1/src/main.c" +#define ECS_MAXENTITIES 100 + #include "ecs2.h" #include "keys.h" +#include "maze_ecstypes.h" #include @@ -20,7 +23,7 @@ #define WIDTH 320 #define HEIGHT 200 #define ASPECT ((float)WIDTH / HEIGHT) -#define SCREENSCALE 2 +#define SCREENSCALE 1 #define SWIDTH (WIDTH * SCREENSCALE) #define SHEIGHT (HEIGHT * SCREENSCALE) #define NEARCLIP 0.01 @@ -29,8 +32,9 @@ #define AVGWEIGHT 0.85 // Game options -#define MAZESIZE 15 +#define MAZESIZE 5 #define HSCALE 1.5 +#define PAINTINGODDS 2 // Maze grows in the positive direction #define MAZENORTH 1 @@ -51,6 +55,8 @@ #define STACKPUSH(s, t, v) s[t++] = v; #define ENDTEXTURE "resources/mazeend.ppm" +#define PAINTINGTEXTURE "resources/specwall.ppm" +#define PAINTINGNAME "painting" // Store all the values users can change at the beginning float ditherstart = -1; @@ -229,18 +235,63 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start, free(mazestack); } -void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) { +// int rand_painting(int size) { +// return (rand() % ()) == 0; +// } + +void create_painting(struct vec2i mazepos, uint8_t dir, + haloo3d_easyinstancer *ins, mecs *ecs, ecs_world *world) { + // Create the painting render instance, set up the ecs instance, etc. + haloo3d_obj_instance *painting = haloo3d_easyinstantiate(ins, PAINTINGNAME); + ecs_eid id = mecs_newentity(ecs, 0); + ECS_SETCOMPONENT(ecs, id, ecs_syncgrow){.obj = painting, + .scale = &world->scaleto, + .basescale = 1, + .timer = &world->scaletimer}; + ECS_SETCOMPONENT(ecs, id, ecs_dieoninit){ + .obj = painting, .render = ins->render, .ws = world->state}; + // Fix up some things based on dir. + switch (dir) { + case DIRNORTH: + mazepos.y++; + break; + case DIREAST: // East also needs the rotation from west + mazepos.x++; + // fall through + case DIRWEST: + vec3(painting->lookvec.v, 1, 0, 0); + break; + } + // OK now that it's setup, we need to put it in the right spot and scale it + vec3(painting->pos.v, mazepos.x * world->state->cellsize, 0, + mazepos.y * world->state->cellsize); + vec3(painting->scale.v, HSCALE, world->scaleto, HSCALE); + // rotation is around the left edge. That's both where we put it AND + // where the painting rotates around. +} + +// Generate walls AND create paintings. Kind of doing too much +void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj, + haloo3d_easyinstancer *ins, mecs *ecs, + ecs_world *world) { // Reset ALL walls obj->numfaces = 0; // Simple: for each cell, we check if north or east is a wall. If so, // generate it. Also, generate walls for the south and west global wall for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { + struct vec2i mazepos = {.x = x, .y = y}; if (!maze_connected(maze, x, y, size, DIREAST)) { haloo3d_gen_grid_quad(obj, x, y, dirtovec(DIREAST)); + if ((rand() % PAINTINGODDS) == 0) { + create_painting(mazepos, DIREAST, ins, ecs, world); + } } if (!maze_connected(maze, x, y, size, DIRNORTH)) { haloo3d_gen_grid_quad(obj, x, y, dirtovec(DIRNORTH)); + if ((rand() % PAINTINGODDS) == 0) { + create_painting(mazepos, DIRNORTH, ins, ecs, world); + } } } } @@ -250,21 +301,33 @@ void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) { } } -// Turning into a blob? IDK. Maybe certain things should be -// global state, which is this. -typedef struct { - // float timedelta; - int fps; - uint8_t state; - uint8_t maze[MAZESIZE * MAZESIZE]; - // int size; - // A suggested start and end. The end is the actual - // end, where we put the ending indicator - struct vec2i start; - struct vec2i end; - // Some simple calcs for you to use - mfloat_t cellsize; -} worldstate; +// // A simple linked list of objects +// struct objlist { +// haloo3d_obj_instance *obj; +// struct objlist *next; +// }; +// +// // Add a new link at the given elem +// struct objlist *objlist_add(struct objlist *elem, haloo3d_obj_instance *obj) +// { +// mallocordie(elem->next, sizeof(struct objlist *)); +// elem->next->obj = obj; +// elem->next->next = NULL; +// return elem->next; +// } +// +// // Free every single element starting at head +// void objlist_free(struct objlist *head, haloo3d_easyrender *r) { +// // void (*freefunc)(haloo3d_obj_instance *obj)) { +// if (head) { +// objlist_free(head->next, r); +// haloo3d_easyrender_deleteinstance(r, head->obj); +// // if (freefunc) { +// // freefunc(head->obj); +// //} +// free(head); +// } +// } enum { WSTATE_INIT = 0, @@ -274,61 +337,6 @@ enum { WSTATE_SPINDOWN = 4 }; -// A component that stores a position and a facing direction -// as an angle -typedef struct { - struct vec3 pos; - struct vec2 rot; // x is yaw, y is pitch -} ecs_placement; - -// A component which links back to a camera -typedef struct { - haloo3d_camera *camera; -} ecs_camera; - -// A component which allows automatic navigation -// of position through the use of timers. -typedef struct { - struct vec3 dest; - int timer; -} ecs_autonav; - -// A component which allows automatic rotation -// through the use of timers. -typedef struct { - struct vec2 dest; // x is yaw, y is pitch - int timer; -} ecs_autorotate; - -// Component which enables synchronized scale y from 0 to 1 or 1 to 0. It is -// expected that an external source is modifying the value -typedef struct { - haloo3d_obj_instance *obj; - mfloat_t *scale; - // When scales are set, they're multiplied by this - mfloat_t basescale; - int *timer; -} ecs_syncgrow; - -// A billboard for OUR system, which does not look up or down at the target. As -// such, no matter what the lookat is set to, y is always going to be equal to -// the y of the instance, so it appears to be looking "straight" -typedef struct { - haloo3d_obj_instance *obj; - struct vec3 *lookat; -} ecs_billboard; - -// A component which holds onto data specifically for world -// entities. You can think of it as private data so people -// can't poke at the worldstate data -typedef struct { - worldstate *state; - haloo3d_obj *wallmodel; - haloo3d_obj_instance *endobj; - int scaletimer; - mfloat_t scaleto; -} ecs_world; - void sys_billboard(ecs_billboard *bb) { // In our current system, the lookvec is the direction it wants to face, not a // "lookat" point. To lookat something, you simply get the vector pointing @@ -397,12 +405,27 @@ void sys_camera(ecs_camera *cam, ecs_placement *p) { cam->camera->pitch = p->rot.y; } -void sys_world(ecs_world *w) { +void sys_dieoninit(ecs_dieoninit *die, mecs **ecs) { + if (die->ws->state == WSTATE_INIT) { + ecs_eid id = mecs_eid(ecs); + eprintf("DELETING SELF: %d\n", id); + // Trivially delete the entity from the renderer + haloo3d_easyrender_deleteinstance(die->render, die->obj); + // Delete ourselves from existence + mecs_deleteentity(*ecs, id); + } +} + +void sys_world(ecs_world *w, mecs **ecs) { const int spinspeed = w->state->fps * 4.0 / (5 * speed); switch (w->state->state) { case WSTATE_INIT: - maze_generate(w->state->maze, MAZESIZE, &w->state->start, &w->state->end); - maze_wall_generate(w->state->maze, MAZESIZE, w->wallmodel); + // We don't need to free anything created from previous runs; they delete + // themselves + maze_generate(w->state->maze, w->state->size, &w->state->start, + &w->state->end); + maze_wall_generate(w->state->maze, w->state->size, w->wallmodel, + w->instancer, *ecs, w); eprintf("INIT MAZE COMPLETE, spinning up walls\n"); maze_to_pos(&w->state->end, w->endobj->pos.v, w->state->cellsize); w->state->state = WSTATE_SPINUP; @@ -441,18 +464,6 @@ enum { SAI_GAMEPLAY, }; -// State for tracking a smart ai moving through the maze. -typedef struct { - uint8_t state; - // uint8_t rotstate; - uint8_t dir; - uint32_t timer; - mfloat_t rotchange; - struct vec2i mpos; - worldstate *ws; - haloo3d_obj_instance *startmarker; -} ecs_smartai; - int smartai_mazeend(ecs_smartai *smartai) { if (smartai->mpos.x == smartai->ws->end.x && smartai->mpos.y == smartai->ws->end.y) { @@ -464,8 +475,8 @@ int smartai_mazeend(ecs_smartai *smartai) { return 0; } -static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, - ecs_autonav *anav, ecs_autorotate *arot) { +void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav, + ecs_autorotate *arot) { const int actiontime = smartai->ws->fps / (2 * speed); const int rotdelaytime = actiontime / 2; // 2 * actiontime / 5; switch (smartai->state) { @@ -475,8 +486,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, if (smartai->ws->state == WSTATE_SPINUP) { smartai->mpos = smartai->ws->start; smartai->dir = - maze_longesthallway(smartai->ws->maze, MAZESIZE, smartai->ws->start.x, - smartai->ws->start.y); + maze_longesthallway(smartai->ws->maze, smartai->ws->size, + smartai->ws->start.x, smartai->ws->start.y); maze_to_pos(&smartai->ws->start, p->pos.v, smartai->ws->cellsize); p->rot.x = dirtoyaw(smartai->dir); // Move startmarker to in front of player. @@ -527,7 +538,7 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, } // Player can only move forward if there's nothing in front of them if (maze_connected(smartai->ws->maze, smartai->mpos.x, smartai->mpos.y, - MAZESIZE, smartai->dir)) { + smartai->ws->size, smartai->dir)) { struct vec2i movement = dirtovec(smartai->dir); smartai->mpos.x += movement.x; smartai->mpos.y += movement.y; @@ -538,12 +549,12 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, // Figure out if a rotation should be scheduled if (!(smartai->mpos.x == smartai->ws->end.x && smartai->mpos.y == smartai->ws->end.y)) { - // Ok we might be moving, we might not be. Let's go ahead and calculate - // rotation based on the FUTURE direction we want to turn. + // Ok we might be moving, we might not be. Let's go ahead and + // calculate rotation based on the FUTURE direction we want to turn. uint8_t rightdir = TURNRIGHT(smartai->dir); uint8_t leftdir = TURNLEFT(smartai->dir); if (maze_connected(smartai->ws->maze, smartai->mpos.x, smartai->mpos.y, - MAZESIZE, rightdir)) { + smartai->ws->size, rightdir)) { // Always choose right over left smartai->rotchange += MPI_2; smartai->timer = rotdelaytime; @@ -553,7 +564,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, // This while loop lets us turn around if necessary, so reaching a // dead end isn't super painful waiting for two rotations while (!maze_connected(smartai->ws->maze, smartai->mpos.x, - smartai->mpos.y, MAZESIZE, smartai->dir)) { + smartai->mpos.y, smartai->ws->size, + smartai->dir)) { // We seem to have reached a wall. Do we need to turn ALL the way // around? We only move left if the player can't move forward or // right @@ -570,30 +582,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, } } -// Setup ECS system for our game -ECS_START(mecs) -ECS_COMPONENT(ecs_world); -ECS_COMPONENT(ecs_autonav); -ECS_COMPONENT(ecs_autorotate); -ECS_COMPONENT(ecs_placement); -ECS_COMPONENT(ecs_camera); -ECS_COMPONENT(ecs_smartai); -ECS_COMPONENT(ecs_syncgrow); -ECS_COMPONENT(ecs_billboard); -ECS_END(mecs) - -// And then a copy of the components here... that sucksssss -ECS_CID(ecs_worldstate, 0); -ECS_CID(ecs_world, 1); -ECS_CID(ecs_autonav, 2); -ECS_CID(ecs_autorotate, 3); -ECS_CID(ecs_placement, 4); -ECS_CID(ecs_camera, 5); -ECS_CID(ecs_smartai, 6); -ECS_CID(ecs_syncgrow, 7); -ECS_CID(ecs_billboard, 8); - -ECS_SYSTEM1(mecs, sys_world, ecs_world); +ECS_SYSTEM2(mecs, sys_world, ecs_world, mecs); +ECS_SYSTEM2(mecs, sys_dieoninit, ecs_dieoninit, mecs); ECS_SYSTEM1(mecs, sys_syncgrow, ecs_syncgrow); ECS_SYSTEM1(mecs, sys_billboard, ecs_billboard); ECS_SYSTEM2(mecs, sys_autonav, ecs_autonav, ecs_placement); @@ -602,6 +592,41 @@ ECS_SYSTEM2(mecs, sys_camera, ecs_camera, ecs_placement); ECS_SYSTEM4(mecs, sys_smartai, ecs_smartai, ecs_placement, ecs_autonav, ecs_autorotate); +// typedef struct { +// haloo3d_easyrender *render; +// haloo3d_obj_instance *paintings[MAXPAINTINGS]; +// ecs_eid paintingecs[MAXPAINTINGS]; +// haloo3d_fb *texture; +// haloo3d_obj *model; +// mecs *ecs; +// mfloat_t *scaleto; +// int *scaletimer; +// int numpaintings; +// } paintingmanager; +// +// void pm_add_painting(paintingmanager *pm) { +// if (pm->numpaintings < MAXPAINTINGS) { +// pm->paintings[pm->numpaintings] = +// haloo3d_easyrender_addinstance(pm->render, pm->model, pm->texture); +// ecs_eid id = mecs_newentity(pm->ecs, 0); +// ECS_SETCOMPONENT(pm->ecs, id, +// ecs_syncgrow){.obj = pm->paintings[pm->numpaintings], +// .scale = pm->scaleto, +// .basescale = 1, +// .timer = pm->scaletimer}; +// pm->paintingecs[pm->numpaintings] = id; +// pm->numpaintings++; +// } +// } +// +// void pm_clear_all(paintingmanager * pm) { +// for(int i = 0; i < pm->numpaintings; i++) { +// mecs_deleteentity(pm->ecs, pm->paintingecs[i]); +// haloo3d_easyrender_deleteinstance(pm->render, pm->paintings[i]); +// } +// pm->numpaintings = 0; +// } + void init_floortexture(haloo3d_fb *floort) { uint16_t cols[1] = {0xFD93}; haloo3d_fb_init_tex(floort, 64, 64); @@ -679,6 +704,10 @@ void init_endtexture(haloo3d_fb *endt) { haloo3d_img_totransparent(endt, haloo3d_fb_get(endt, 0, 0)); } +void init_paintingtexture(haloo3d_fb *endt) { + haloo3d_img_loadppmfile(endt, PAINTINGTEXTURE); +} + void init_billboard(haloo3d_obj_instance *bb, mfloat_t scale) { // Haven't actually generated the object yet, oops. We don't let billboards // all share the same model, as they might require slightly different @@ -711,6 +740,56 @@ void init_mazeinstances(haloo3d_obj_instance *floori, ceili->pos.y = 1; } +// Given a pointer into an obj, fill it with everything required to make +// the painting that clips with the wall (it's a cube) +void create_paintingobj(haloo3d_obj *obj) { + // 2 for each face; we have 4 faces (top and bottom don't need anything) + haloo3d_gen_obj_prealloc(obj, 8, 8, 8); + // ppm is 128x128 but 1 pixel along the top is the wall side + const mfloat_t ptextop = 1.0 / 128.0; + const mfloat_t thickness = 1.0 / 64.0; + // box will be aligned along x/y axis, so it will be "facing" the negative z + // dir like most other models. Box is topleft, topright, bottomleft, + // bottomright, then same on other side. Box is not centered around 0, + // intstead it is the same as a wall where iti starts from y=0 and goes to + // y=1 + vec4(obj->vertices[0].v, 0, 1, thickness, 1); + vec4(obj->vertices[1].v, 1, 1, thickness, 1); + vec4(obj->vertices[2].v, 0, 0, thickness, 1); + vec4(obj->vertices[3].v, 1, 0, thickness, 1); + vec4(obj->vertices[4].v, 0, 1, -thickness, 1); + vec4(obj->vertices[5].v, 1, 1, -thickness, 1); + vec4(obj->vertices[6].v, 0, 0, -thickness, 1); + vec4(obj->vertices[7].v, 1, 0, -thickness, 1); + // Now, the vtexture points. Some might be dupes, I don't care. First 4 are + // the painting texture, next 4 are the wall texture + vec3(obj->vtexture[0].v, 0.001, 0.999 - ptextop, 0); + vec3(obj->vtexture[1].v, 0.999, 0.999 - ptextop, 0); + vec3(obj->vtexture[2].v, 0.001, 0.001, 0); + vec3(obj->vtexture[3].v, 0.999, 0.001, 0); + vec3(obj->vtexture[4].v, 0.001, 0.999, 0); + vec3(obj->vtexture[5].v, 0.999, 0.999, 0); + vec3(obj->vtexture[6].v, 0.001, 1.0 - ptextop, 0); + vec3(obj->vtexture[7].v, 0.999, 1.0 - ptextop, 0); + // Preconstruct the simplified format of the face vertices and vtexture. + // First 3 are vertices, next are vtexture + // clang-format: off + const uint8_t f[8][6] = { + {0, 2, 3, 0, 2, 3}, // front face + {0, 3, 1, 0, 3, 1}, {5, 7, 6, 0, 2, 3}, // back face + {5, 6, 4, 0, 3, 1}, {1, 3, 7, 4, 6, 7}, // front side + {1, 7, 5, 4, 7, 5}, {4, 6, 2, 4, 6, 7}, // back side + {4, 2, 0, 4, 7, 5}, + }; + // clang-format: on + for (int fi = 0; fi < obj->numfaces; fi++) { + for (int v = 0; v < 3; v++) { + obj->faces[fi][v].posi = f[fi][v]; + obj->faces[fi][v].texi = f[fi][v + 3]; + } + } +} + int main() { // int argc, char **argv) { haloo3d_easystore storage; @@ -725,6 +804,8 @@ int main() { // int argc, char **argv) { render.tprint.fb = &screen; eprintf("Initialized renderer\n"); + haloo3d_easyinstancer instancer = {.storage = &storage, .render = &render}; + haloo3d_easytimer frametimer, sdltimer, filltimer, logictimer; haloo3d_easytimer_init(&frametimer, AVGWEIGHT); haloo3d_easytimer_init(&sdltimer, AVGWEIGHT); @@ -736,31 +817,40 @@ int main() { // int argc, char **argv) { haloo3d_obj *wallo = haloo3d_easystore_addobj(&storage, "walls"); haloo3d_obj *starto = haloo3d_easystore_addobj(&storage, "start"); haloo3d_obj *endo = haloo3d_easystore_addobj(&storage, "end"); + haloo3d_obj *paintingo = haloo3d_easystore_addobj(&storage, PAINTINGNAME); haloo3d_fb *floort = haloo3d_easystore_addtex(&storage, "floor"); haloo3d_fb *ceilt = haloo3d_easystore_addtex(&storage, "ceiling"); haloo3d_fb *wallt = haloo3d_easystore_addtex(&storage, "walls"); haloo3d_fb *startt = haloo3d_easystore_addtex(&storage, "start"); haloo3d_fb *endt = haloo3d_easystore_addtex(&storage, "end"); + haloo3d_fb *paintingt = haloo3d_easystore_addtex(&storage, PAINTINGNAME); haloo3d_gen_plane(planeo, MAZESIZE); haloo3d_gen_grid(wallo, MAZESIZE, 0); + create_paintingobj(paintingo); init_floortexture(floort); init_ceilingtexture(ceilt); init_walltexture(wallt); init_starttexture(startt); init_endtexture(endt); + init_paintingtexture(paintingt); eprintf("Initialized models and textures\n"); worldstate wstate; memset(&wstate, 0, sizeof(worldstate)); + // The maze won't change size (for now), so we can set it here to some + // constant array + uint8_t maze[MAZESIZE * MAZESIZE]; + wstate.size = MAZESIZE; + wstate.maze = maze; wstate.fps = fps; wstate.state = WSTATE_INIT; wstate.cellsize = HSCALE; // Lighting. Note that for performance, the lighting is always calculated - // against the base model, and is thus not realistic if the object rotates in - // the world. This can be fixed easily, since each object gets its own + // against the base model, and is thus not realistic if the object rotates + // in the world. This can be fixed easily, since each object gets its own // lighting vector, which can easily be rotated in the opposite direction of // the model struct vec3 light; @@ -779,7 +869,7 @@ int main() { // int argc, char **argv) { init_mazeinstances(floori, ceili, walli); init_billboard(starti, 1.0); init_billboard(endi, 0.25); - eprintf("Setup all object instances\n"); + eprintf("Setup all static object instances\n"); unigi_type_event event; unigi_type_resolution res; @@ -817,11 +907,15 @@ int main() { // int argc, char **argv) { // Set up ECS entities. For this game, we mostly have global entities. mecs ecs; mecs_init(&ecs); + eprintf("ECS sys size: %zu\n", sizeof(mecs)); ecs_eid worldid = mecs_newentity(&ecs, 0); eprintf("World eid: %d\n", worldid); - ECS_SETCOMPONENT(&ecs, worldid, ecs_world){ - .state = &wstate, .wallmodel = wallo, .endobj = endi, .scaletimer = 0}; + ECS_SETCOMPONENT(&ecs, worldid, ecs_world){.state = &wstate, + .wallmodel = wallo, + .endobj = endi, + .scaletimer = 0, + .instancer = &instancer}; ecs_world *eworld = ecs.c_ecs_world + worldid; // Setup some dynamic objects @@ -909,6 +1003,7 @@ int main() { // int argc, char **argv) { sys_autorotate_run(&ecs, i); sys_camera_run(&ecs, i); sys_billboard_run(&ecs, i); + sys_dieoninit_run(&ecs, i); } haloo3d_easytimer_end(&logictimer); diff --git a/maze_ecstypes.h b/maze_ecstypes.h new file mode 100644 index 0000000..f87ffa9 --- /dev/null +++ b/maze_ecstypes.h @@ -0,0 +1,125 @@ +#ifndef __MAZE_ECSTYPES +#define __MAZE_ECSTYPES + +#include "ecs2.h" +#include "haloo3d/haloo3d.h" +#include "haloo3d/haloo3dex_easy.h" + +// Turning into a blob? IDK. Maybe certain things should be +// global state, which is this. +typedef struct { + // float timedelta; + int fps; + uint8_t state; + uint8_t *maze; //[MAZESIZE * MAZESIZE]; + int size; // The length of an edge, guaranteed to be a square + // A suggested start and end. The end is the actual + // end, where we put the ending indicator + struct vec2i start; + struct vec2i end; + // Some simple calcs for you to use + mfloat_t cellsize; +} worldstate; + +// A component that stores a position and a facing direction +// as an angle +typedef struct { + struct vec3 pos; + struct vec2 rot; // x is yaw, y is pitch +} ecs_placement; + +// A component which links back to a camera +typedef struct { + haloo3d_camera *camera; +} ecs_camera; + +// A component which allows automatic navigation +// of position through the use of timers. +typedef struct { + struct vec3 dest; + int timer; +} ecs_autonav; + +// A component which allows automatic rotation +// through the use of timers. +typedef struct { + struct vec2 dest; // x is yaw, y is pitch + int timer; +} ecs_autorotate; + +// Component which enables synchronized scale y from 0 to 1 or 1 to 0. It is +// expected that an external source is modifying the value +typedef struct { + haloo3d_obj_instance *obj; + mfloat_t *scale; + // When scales are set, they're multiplied by this + mfloat_t basescale; + int *timer; +} ecs_syncgrow; + +// A billboard for OUR system, which does not look up or down at the target. As +// such, no matter what the lookat is set to, y is always going to be equal to +// the y of the instance, so it appears to be looking "straight" +typedef struct { + haloo3d_obj_instance *obj; + struct vec3 *lookat; +} ecs_billboard; + +// A component which holds onto data specifically for world +// entities. You can think of it as private data so people +// can't poke at the worldstate data +typedef struct { + worldstate *state; + haloo3d_obj *wallmodel; + haloo3d_obj_instance *endobj; + haloo3d_easyinstancer *instancer; + // paintingmanager * pm; + int scaletimer; + mfloat_t scaleto; +} ecs_world; + +// State for tracking a smart ai moving through the maze. +typedef struct { + uint8_t state; + uint8_t dir; + uint32_t timer; + mfloat_t rotchange; + struct vec2i mpos; + worldstate *ws; + haloo3d_obj_instance *startmarker; +} ecs_smartai; + +// A component which allows an object instance to die +// when the maze is initiailized. +typedef struct { + haloo3d_obj_instance *obj; + haloo3d_easyrender *render; + worldstate *ws; +} ecs_dieoninit; + +// Setup ECS system for our game +ECS_START(mecs) +ECS_COMPONENT(ecs_world); +ECS_COMPONENT(ecs_autonav); +ECS_COMPONENT(ecs_autorotate); +ECS_COMPONENT(ecs_placement); +ECS_COMPONENT(ecs_camera); +ECS_COMPONENT(ecs_smartai); +ECS_COMPONENT(ecs_syncgrow); +ECS_COMPONENT(ecs_billboard); +ECS_COMPONENT(ecs_dieoninit); +ECS_END(mecs) + +// And then a copy of the components here... that sucksssss +ECS_CID(ecs_worldstate, 0); +ECS_CID(ecs_world, 1); +ECS_CID(ecs_autonav, 2); +ECS_CID(ecs_autorotate, 3); +ECS_CID(ecs_placement, 4); +ECS_CID(ecs_camera, 5); +ECS_CID(ecs_smartai, 6); +ECS_CID(ecs_syncgrow, 7); +ECS_CID(ecs_billboard, 8); +ECS_CID(ecs_dieoninit, 9); + +#endif diff --git a/resources/specwall.ppm b/resources/specwall.ppm index 0b9accc..3de06a5 100644 --- a/resources/specwall.ppm +++ b/resources/specwall.ppm @@ -1,1330 +1,5 @@ -P6 128 128 15 -                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                                                         - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                                             - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -                 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -            - - - - - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - -                 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -          - - - - - - - - - - - -                                                        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -        - - - - - - - - - - - - -                                                                       - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -       - - - - - - - - - - - -                                                                                                 - - - - - - - - - - - - - -     - - - - - - - - - - - -                                                                                                   - - - - - - - - - - - -    - - - - - - - - - - - -                                                                                                    - - - - - - - - - - - -  - - - - - - - - - - - -                                                                                         - - - - - - - - - - - - - - - - - - - - - - -                                                                                       - - - - - - - - - - - - - - - - - - - - - -                                                                                       - - - - - - - - - - - - - - - - - - - -                                                                             - - - - - - - - - - - - - - - - - -                                                                           - - - - - - - - - - - - - - - -                                                                       - - - - - - - - - - - - - - -                                                                     - - - - - - - - - - - - -                                                                  - - - - - - - - - - - -                                                             - - - - - - - - - -                                                           - - - - - - - -                                                             - - - - - - -                                                       - - - - - -                                                 - - - -                                             - - -                                                   -                                              -                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               \ No newline at end of file +P6 +# CREATOR: GIMP PNM Filter Version 1.1 +128 128 +255 +ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffffUUUUUUUUUUUUUUUUUUUfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwwwwwffffffffffffffffffffffffffffffffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwffffffffffffffffffffffwwwwwwwwffffffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwffffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwfffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww""ˆ""ˆwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwwwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆwwww""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™fD""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™fD""""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ªD3""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª3""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ªf"3""""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ªf"3""""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""ˆ""ˆ""ˆ""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª3"D"""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""ˆ""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª3""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª3""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª3"""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ªD"""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»3D""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»33»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»33»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»333»33»33»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""™""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»"33»33»33»33»33»33»33»33»33»33»33»ÿîÿî33»33»33»33»33»33»33»33»33»33»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""™""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»ff™fff™™Uw"3UUˆˆ33»33»33»ÝDDÝDD33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»""»""»""»""»""»33»33»33»33»33»33»33»33»33»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì™™™fff™™™www"33UU"33»33»D™"fÌD33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»""»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì™fff™™ffffwUUw3D3"""33ÌD™"fÌD33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33̈ˆfff™™ff™ffffUUUUU3D""""wDDDUU33Ì33Ì33Ì33Ì33ÌîUU33ÌîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ìfffff™™ff™ffff™UwwUww""""DDDUU"ww33ÌÝDDîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ìfˆ™™ffˆfˆf™ffffwUwwUwU""""DDDU"""ffˆ33Ì33Ì33Ì33Ì33Ì33Ì33ÌîUU33ÌîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ìÿî33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ìf™ˆfˆˆfffˆ™™f™f™DDUDUUU"DDDDU"fˆfˆf33Ì33Ì33Ì33ÌÝDDîUUîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33ÝÝDDîUU33ÝîUU33Ý33Ý33Ý33Ýffff™ˆˆˆUff™™fffDDUDUUUwDDDUU""DDfˆ""33Ì33Ì33Ì33ÌÝDDfÌD33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33ÝÝDDÿîîUUîUUff™UU™™ˆUUUˆˆˆfffff"DDDUUUUw"D"DU"""fff"3DD™"D™"fÌDfÌD33ÌîUUîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33ÝîUUîUUfD™"ÝDDfÌDf™UUwUfffUUUˆˆUˆffff"DDDUDUUUU"""""U""DDD""D3D3"33ÌÝDDîUU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33ÝÝDDîUUîUUD™"™ffwwUUw™fˆˆˆˆUwˆˆˆfff""DDDUDwUwU""D"""fDff""ff33DD™"fÌD33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""»""ª""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33ÝîUUîUU33Ý33ÝîUUîUUD™"ÝDDîUUf™fwUwwUU™fˆˆˆˆUwUUˆˆff"""DUDUwwUwU"""""ffDD3fff33D33Ý33ÝUU33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»""»""»""»""ª""ª""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33ÝD™"ÝDDîUU33ÝîUUîUUfD™"ff™™UUUwwUfˆfUUUUwUˆUˆˆf"DUDUUUUUUU"""""DDffDDDDDDf"3fUwwUˆfw33Ý33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""»""ª""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý33ÝUÝDDÿîîUUUfffffUUUUUwUfˆfUwwwUˆˆˆUUˆ""DDDwUwUwUw"""ffDDfDD3DDDD""33ˆUˆDUDD33ÝîUUîUU33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""ª""ª""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33Ý™™D™"ÝDDfÌDf™ffffUwUwUUf™™™UwUwUˆUˆˆUD"DDwwUwUfD""""DDfDDD"3DDD"3wwUDDDff33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»""»""»""»""ª""»""»""»""»33»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33ÝDDD™"D™"ffffˆfUUwUww™™™™3UwwUUUˆUˆUUUDDUUUDffDf""""DDffD3"""DDDUDDDfDDUw3îUU33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""ª""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33݈ˆD™fD™"™fffˆfwwUwUf™f™U3UUwUwˆˆˆUˆDD""DwDfffDDf""""DffDD3"DD"D"UUÝDDîUUîUUDUw"33Ý33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»""»""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33Ý33ÝÝDDUUÝDDîUUîUU™fffˆfwwwUUf™fffUUUUUwUˆUˆUUUUU""DfffDDDfDDDUDff33"fD3DDU3ÝDDfÌDˆfU"îUUîUUîUU33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33ÝfDUUUUD™"ÝDDfˆˆffˆfUUˆˆˆfUUw3UU3UUwUˆUUUDDDD"DDfDDDDfDD"DD"wwffDDDDD3D3UD™"fÌD3ˆU"ÝDDÝDDfÌDÝDD33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33ÝÝDDˆfUwUUˆU™fˆˆf™f™™ffUUwwUUw33U33UUˆˆˆˆUUUU"""DDffDDfDD"""DwUUfD3DDDDDU33D"UUU3ˆˆfÌDÝDDîUU3333Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»""»33»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ý33Ý33Ý33ÝfUwwwUUUf™ffffff™™3UUwwUwUw3UUU3UUUUUDDDDD""DfffDDfDDf""D"UUwU3DDffDffU3D33333DDDffÌDf33Ý33Ý33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»""»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33ÝDÿîUfUUwUwUUˆ™f™ffff™f3U3UUwwUww3UU3UUUUUUUUUUUD""DDfDffDDfDDD"DUwwwwU3fffDfD33DD333Dff3UU33Ý33ÝîUUîUU33Ý33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33ÝUDÝDDUUUUUUUUUU™f™f™ff™fU3UUUwwwUUw33UˆˆUUUUDDDDDU""DDffffDDfDDD"DwwUDDDD3DffDDDf3ÝDDÝDDîUUîUUf33U"3U3fÝDD33Ý33Ý33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33ÝU""DDUwUUwˆUˆUf™™fffffU3U33UUwwwwUw3ˆˆUUˆUUUUUUUDD""DffffDDfDDDD"DDDDwwwf3DDD33UwfD™"fÌDfÌDfDf3UU"UUU"îUUîUUîUUw33Ý33Ì33Ì33Ì33Ì33Ì33Ì33»33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33Ý33Ýw""fDUwUUfˆˆUUf™™™ff™fUU3UU3UUUwUwwUDDffDDfUUUUUwww"""DDfffDDfDDfDD"DDwDDwDfD33U33wUU33D™"DfffUUU3DUDÝDDîUUˆfw33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33»33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33ÝDD™UîUUfˆDUDUUf™™f™ff™f™fw3UUUU3UUwUwU™DfDDffDUUUUUUUD"""DDffDDfDDfDD3DDDDwwDff3UU3UUUwwwU3UUU"UDwÝDDÿîîUU3U"33Ý33Ì33Ì33Ì33Ì33Ì33Ì33»33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33ÝDîUU™ˆUÝDDUUUDUDDf™™™fff™ffwUU3U3U33UUwfff"DffDffwUUUUUUD3"""DfffDDfDˆUˆUDD""wDDfDf33U33wwUUUU3UUU"DUUDD™"ÝDDÝDD3DDÝDDÝDD33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33ÝîUUDîUU™îUU"UˆUDUwwf™ff™™ff™UwUw333UUU3ff™ff"DffDDfUwUUUUU33DffDDUUUˆUUˆ""DDDDfDf"3U33UUUwwwwwUU"DDU33fÌDD™"3fDfD33Ý33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ý33ÝDîUUÿîîUU"""ˆˆUUDDDwf™™™f™fUwUwww3U3U3™fff™""DffDDwUUUUUU3D3"DffUUUˆˆˆˆˆUUDDDDDfDD33UwwwUUUUUDîUUÿîDDfD3333fDffU33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33ÝUDfÝDDÝDDfÌD"UUUUDDDfffff™™™UwUUUU3U3U3f™fff""DffDUwwUUUUDD3""UUUˆˆˆUUUUUˆU"""DDfDDf3UUUUUwwww""ÝDDfÌDÝDD"fDfD3DUDUîUUîUU"33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33Ì33ÝUU™™fD™"fÌDfÌD""UUwˆDDDffff™f™3UwwUUUU3UU™f™™ff"""DffDwUUUUUUDDD3"UUˆUˆˆˆˆˆˆˆUˆˆ"UwUUwU3wwwwUUUUD"fÌDD"fDfDf"DUfÝDDÝDDˆD""33Ì33Ì33Ì33Ì33ÌD"""UUf™f™f"UwUˆUD™™ff™f™3DDUUwwww3U3™fff™f""""DDfUwwwwUU33D33"ˆˆUUˆUˆˆˆUUUUUUîUUUwUwwU3UUUUUwww""UUfDfDff"33DDU3DU33Ì33Ì33Ì""""U™™™ff""UUUUD™™f™f™D3D3UUwwwwU3f™fDDDD"""DDwUwUUwU333D3"ˆUUUUˆˆˆUUˆˆˆˆˆUîUU"UwUwwwwwwUUU""UDDfDDD3D""ÝDDÝDD33Ý33Ì33Ì""3îUUîUUîUU™™™fˆ""UUUˆUf™fffD3DD3DUUUUUwwDDDDDfDD"""DDUUUwwUUDD3DD3UUˆˆUUˆUˆˆUUˆUUUUU"UwUwUUUUwww""""UUDDDDfD"D3fÌDDff3f3îUUîUUfÌDfÌDfUwfU""UˆffˆffffDD3D3DUUUUUwwDDDDfDDD"""DwwwUUUU33D3D3UˆˆUˆUUUUUUˆUDfDDD""UUw"UUUwww"""""DDfD"3"Dff333D33îUUfÌDfwUwfˆ"""ffDfDfDU3DDD3D3UwwUwwDDfDDDDff""UUUUˆˆww333D3DˆˆUˆˆˆˆUDfDDDDfDfDf"UUw""UUwUU""""DDDffD""UfUwUDDÝDDÿîîUUDwwUwfˆU""UUfUDfDfDww3D3D33UwUwwUDDDDDDffD""UUUˆˆUUUUU33DDD3UUUwwwwwDfffDDfDfDfUU"""UUU"""DDffDD""wwDw33Ý3îUUîUUÝDDfÌDUUUUUUU"wwwUfUDfDfDUw3D33333UwwUUffDDDDffDD""UUUUUUˆwUwU3DDDDUUwwUUUwDDDffDfDDfDU"""UU""""""DfDDffD"33DDU33ÝDÝDDÝDDfÌDfÌDfÌDUUUUUˆUUUUwff3UDfDDUUU3D3D33UUUUUfDDDDDDfDDD"UUUUUˆˆUwUw3DDD3UUUUwwUU"DfDDfffDDfD""""3U"""""333D""Dˆ3DD™""fD™"D™"UUUDDDˆUUUUwffˆ3UDfDfwww3DDDDD3UUwUfDDDDDDDDDf""wUUUˆUUwUwUU333DU3UwwwUU"DfDDDDfDfDD"DD"""""""3DD3"ffUUU"""33DD3DUUwUUˆffU3U3DfDwwwU3D3DD3UUwwfDDDDDDDfDff"wUUwwUUUUwUwwU3333UUUUwww"DffffDDDfDDDDD"""DU""33D""ffUU"U33D3wUUwUwˆffU3U3DfDUUUw3D33DDDUwwDDDfDDDDffffwUUwwUUˆwUUUUwU333U3UUwww"""DDDfffffDDD™"33D3DD"wU33D""""Uw3""D3D33wUUwUUfˆf3U3U3DfwwwUw333D3DUwwDfDffDDfffDfDwUUwwUUUUwwwwUww3U3UU3UUw"DfDDDffDDDDf™ff™DD3"3DDwwww""333"33îUw""UD333UwUUwUfff3U3UUDfwwwUU3D3333DUUDffffDDfDfDfDDwUwwwUUUwUUUUwUUwU3U3UUUw""DfffffDDDDf™™ff™™ff"""3DDDUwU"33"""""""""DU333UwUUwˆffˆUU3UU3DUUUwwUDDDDDDUUfffDfDDfDfUUUDDDfffDDDDffDDDDD33D333U3U"""DfDffDDDDfDˆˆˆfˆfˆD""3wwwUwU3D""""""""UD33wUUUUˆˆf"3UU3U3DwwwUwD3DD33D3UfDfDfDDUUUUUUDDDDDfffDDffDffDD3U3DD3DD3"""DfDffDDDDfDˆˆˆˆfˆfD""3wwwDwww33""""""""DU33wUwUwfˆf3U33UUUUwwUUff3D3D33UfDffffUUUUwUUffDDfffDUUDDDDffD3U3DD3DD3""DfffDDDDfDfˆˆˆˆfˆ33""DDDwwf"3"""""""""""UDU3UwUUfff™""3UU3UUUUwUwDD3D3DDD3ffffffUUUUUUUfffDDDffDDDffDDDD3UU3DD33D"""DfffDDDDfDfDˆˆˆˆf333""UUUww"3""""""""""""DUU3UwU™™f™3U33UwwUUwwDDf3D3D3™ffff™™33UUUUUDDDDfffDDUDDffDff3UU33D33D"""DffDDDfˆˆfffˆˆˆD3Dw""UUww""""""""""UUDUf™™fff™"3UU3UUUwwUffD3D3D3™™ffff333UUUwUDDDDDDDfUUUDDfDff3UU333D33""""fˆˆffˆˆˆˆfUfˆˆDDDUw"UwîUUD"îUUîUUD"""""""""fffff™™ff™""""3333wwUUwwffDD3D3Dfffff™U333UUUUffffDfffUDUDDDDDD3UU333DD3""""Ufˆˆffˆfˆˆ33fˆ3D33UwDÝDDîUUîUUîUUÿîÿîîUU"""""U""""fffff™™f™f"3UUUUwUwwDDff3D3Dff™fffUUU3UUUUfffffDDDDUDDDffDDU33UU3D33""""Uˆfˆˆffˆff3U"f333DDUwD™"ÝDDîUUfÌDÝDDfÌDîUU"UU""U""ff™fff™f™™f"""""333wUUUUUffDDf3D™f™fff3UUU3UUUUDDDDDDffUUUUUDfffU33UU3D33""""ˆUˆffˆfˆˆfUUU"D3DDfUwD™"fÌDD™"ÝDDfÌDD™"fÌDD3fÌDîUUîUU""D™™fˆˆˆff™f™f""3UUwwwUUffDDf3D™™ff™f333U33UUUDDDDDfDDUDUDDDDDDU33UU33DD""""ˆUUˆffffˆˆU3U3"33DD3wUUD™"D™"33DfDD"D™"ÝDDfÌD""D""™ˆˆˆˆˆf™f™™f™""""33wUUUUUDDffDD3f™f™f™U333333UUfffffDDfDUDDUDDfDU33UU33DD"""UUUUˆfˆˆff3U33"D3DD33wUD™"3"3D""fÌDD™""UUDˆˆˆfffˆˆDfDfDf"""""3UwwwwUffDDff3ff™fˆ33333333UfffffDDDUUUUUUUDfU33UU333D"""UˆˆUUUfˆˆfUUUU3"33DD33w3D3DˆU"3D"UUwUUUUffˆˆ"DfDfff3wUUUUUDDffDDffˆffˆ""33333333DDDDDUUUUDUDDDDDfU33UU3333""""ˆˆˆˆUUUfˆˆU3U3U33D33D3ww3D3UˆU"DD""fÌDÝDD™DUˆUˆfffˆ"DfDDDfD"""UwUwUDDffDDffffˆfˆ3333333DDDDDDDDUDDDDDDDDDU33UU33U3""""ˆUUˆˆˆUUff3U333U3D33DD"w"33D3Uˆˆ"D3DfÌDD™"3DUˆUUfˆˆ""DfDfDf"wUwUwUfDDfDDfˆfˆˆff"333D33DUDDDDDDUwDDDfDfDf3DD33DD33"""îUUÿîÿîUîUUˆˆˆUUfUUUU333D333DDw"3333ˆˆˆˆD3D"D3UUˆUffˆ"DfDfDf"UUwUwUDDDDffDfˆfˆˆf"""33333DUDDDDDDDUwDDDDffff3DD33DD3D"""ÝDDÝDDîUUîUUUUˆˆˆUUUU3U3U3U3D333"3""333ˆˆUˆU3333UUUˆfˆ"DffffD""wUwUwUwDDDffDDfffˆff"33333UDDDDDDDwUwDDfDfDf"3DD33DDDf"D™"D™"D™"fÌDîUUˆˆUUUwUUD33D333U33DD33D"DDÿ33333"ˆˆffˆˆ33UUˆUff"""DfDffDUwwUwUwffDDDfDˆˆfˆf"""33333DUDDDDDDwUwUDDDfDf3DD33DDDf"""D™"D™"ÝDDˆUwwUUwwDD33D3DDDDDDD33"3"33UUwU333UUUˆf"""""DfDDDfîUU"wUUUwUwffDDfDDˆˆfff"""33D3DUUDDDDDwUwUDDDfDf"3DD33DDfD""""D™"UUwwUUwwUDD33D3DDDD"DD3D3"""3""Uww3DDUˆˆUf"""""DfDDffîUUfÌDwwwwîUUUwDDffDffffˆˆfˆ""3333UUUUDDDDwUwUwDDfDf"3DD33DDfD"""D™"D™"wwUUwwUUDDf33D3DDD3"DD33""3wU3DDUUUˆU""DfÝDDÿîÿîîUUfÌDfÌDUwUUwîUUfÌDffDDfDDˆˆffˆf""""333UDDUUDDDUwUwUUDDDD""3DD33DfDf"""fD™"UUwwUUwwDDfD33D3DD3"DDDDD""DDÿ"""w33DUˆˆf""""DfffÿîÝDDfÌDwUwÝDDÿîÿîîUUfÌDffDDfDfˆˆffˆf"""333DDDDUDDDUwUwUUDfDf""3DD33DfDfD"DfUwwwUUwwDDfD33D3DDUU"DDDD""""""3D3fffD"""DîUUîUUÝDDD™"fÌDfÌDfÌDwUUÿîÝDDfÌDDDffDDDffˆˆfˆ""""33DUDDDDDDUwUwUUwDDD"""333DffDfD""fffUUwwwUUDDfDf33D3DUUU"DDD3"""""3Dfff""D"""DfÝDDD™"D™"D™"wUUîUUîUUÝDDD™"D™"fÌDfÌDDDffDˆˆfUww"33UUUUDDDDwUwUwwUwDD"""333DffDfDD"DDDUwwUUUwffDfDf33D3U3U"DDDUU"""DD™ffDDD"""""fffD™"UUUwwÝDDD™"D™"D™"DDwwDDwUwwUwwD""""3UDUUUDDDwUwUwwUwDD"""333ffDfDD"ffffUUwwUUffDfDf33D3U3U3"DDU3U"""fÌDfÌDD3fff"""""""ˆfffD™"wUUwUwwD™"DDwwDDwDUwwUwwD""""UDDDUUUDwUwUwwUwUD""""333ffDfDDDDDDDfUwwUUffDfDfD33D33333"DD33""""3fÌD"D™™fDDDDD"""UffˆˆUUUUUwwwfDwDDwwDUUUUUUDD"""""DfffDfffDfDfDDfDfD"""33ffDfDDDfffDfDfUUwwffDfDfD33D3U3U3"DD3U3""fÌDfÌDD™"3f™f""""""""ˆˆffˆfUUUUwwwwDfDDwDDwDUwwUwDD"""""DDfffDDDfDfDffDfD""33ffDfDDDfDDfDfDUwwUffDfDfDf333U3U33"DUUU3""D™"D™"3™ffDDDDD""""UUffˆwwwwUwwUfffDwwDwwDUwwUwDDD""""DDfffD"DfDfDffDDf""3ffDfDDDfDffDfDfDUUwffDfDfDfD3UUUUU3"DU3U3U""D™"D™"3f™""""""D""ˆˆˆfffwwwwUUUwDDDDDwDDDwDUUUUDDD""DDffff"DfDfDffDDf"""3ffDfDDDfDffDfffDfUwffDfDfDfD3UUUUU3U"D33UUU"D3™f™DDDDDD""ˆUUˆffUUUUUUwwfffDDwwDDwwUwwUwDDD""""DDDff"""DfDfDffDfD"""f™f™fff™ff3UUUDDffUffDfDfDfDfU3U3UUUU"3U3U3""fÌDDf™fD"""""D"UˆˆˆˆfˆwwwwwUwwDDffDDwwwwwUwwUwDDD""DDDff"""DfDfDffDfD""f™™™f™fff™D3U3U3333UUˆUˆUˆUˆUˆU3U3UUU"UU3333"DfÌD™Uw"DDD"DDDˆˆUUUfwwwwwUUUffDDDfDwwDDwwUwwwDDDDDDDD""DfDfDfDfDf"""ˆf™f™™™f™fDfU3U333UUUˆUˆUˆUˆUˆDffD33U3UUU3U33"DfÌDUww"DD""""DUUˆˆUˆfUUUUUwwUDDfffDDDDDDDwUUUwDDDD"""DfDD""DfDfDfDfDf"""ff™f™™f™™™ff3U333U3UUˆUˆUˆUˆUˆUDDDffDffU3UUUU3"33wUw"""DDDD""ˆˆˆUˆUfwwwwwUUUffDDDfDwDwDDDDUwwDDDDD""""DffDDfDffDfDf""fˆff™™f™™ffDD333UUUˆˆUUˆUˆUˆUˆUUDffDDfD333333UUfÌDD™"UwUD"DDD"""UUUˆUˆˆUDDDDDffffDfDfDfDwwwwDDUwwDDDDDDDf""DDfDfDfDff"ˆffˆ™f™™™ffDfD3UUU3ˆˆUUˆUˆUˆUˆUUwDDDffD333333D3fÌDwUwD""""DDDˆUˆUUUUDDDDDDDUDffDDDfDwDwwwDDUwDDDDDD""""DD"""DDffDfDffD"ˆfˆffff™f™DDff3UUU3ˆˆUˆUˆUˆUˆUwUwwDffDDf33D3D3D3D™"UUUf"DDDDDUUUˆˆUˆU"DDfffffUDfDfDffDwDDDwwwUwDDDDDDD""""DD""""""DDffDfDffD"fˆfˆff™f™fDffff3U3UUUˆˆUUUˆUˆUwwwwUDfDDf"333D3D3fÌD3UUf"D""""ˆUUUUˆˆˆDDffffUDfDDDfDDDfffDDDUUUUwwwD""""""D""""""DDfDfDffDf"ˆffˆˆffff™DfffDD333UUˆUˆUUˆUˆUwwUwUUDfffD333DDDDÝDDUUUfD"DDDDˆˆˆUUˆU""DDDfffwwDDffff"DDDfffDUUUwwwUD"""D"""DDfDfDffDf"ˆfˆfffˆf™™ffDfDf33UˆUˆUˆˆUUUˆUwwUUUUwDfDD333DDD3UUfD""""UUUˆUUˆU"DDDffwUDDffff"DDfDDDDUUUUwwUDf""""""DfDfDffDfDfˆfˆfˆfˆffffDDDff3UˆˆUîUUˆˆUˆUˆUwwUUwUwwDfff33333D"3UwfD""DDˆˆUUUUUU""""DDfDDwUDDfffDDfffDDwUUwwwUDf""""""DfDfDffDfDˆffˆˆfˆˆfffDDDffff3ˆfÌDUîUUUUUˆˆUˆUwUUwwUwUDfD"3D33D \ No newline at end of file