From d27b72fbe8c16721fd92265db0c86df345dac2a9 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 22 Jan 2019 03:10:11 +0100 Subject: [PATCH] server, cpp client, smooth turnTo direction --- CitizenClass.pde | 25 +-- Entities.pde | 50 ++++-- Map.pde | 24 ++- Server.pde | 30 ++++ UI.pde | 8 +- citizen_server.pde | 124 +++++++++++++++ client/client | Bin 0 -> 77600 bytes client/main.cpp | 362 ++++++++++++++++++++++++++++++++++++++++++++ data/server/map.txt | 270 +++++++++++++++++++++++++++++++++ 9 files changed, 862 insertions(+), 31 deletions(-) create mode 100644 Server.pde create mode 100644 citizen_server.pde create mode 100755 client/client create mode 100644 client/main.cpp create mode 100644 data/server/map.txt diff --git a/CitizenClass.pde b/CitizenClass.pde index 89206be..2972665 100644 --- a/CitizenClass.pde +++ b/CitizenClass.pde @@ -45,7 +45,7 @@ void initCitizen() { if (i != i_selectedCitizen) citizen[i].spawn(citizen[i].i_home); - else citizen[i].spawn(100, 100); + else citizen[i].spawn(8, 8); if (citizen[i].b_randomRun) citizen[i].goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)), 10); //bad } @@ -73,7 +73,6 @@ class Citizen extends Entity { float f_FOV = PI / 4.0; int i_visionDistance = 60; boolean b_randomRun; - GraphNode startNode, endNode; int startNodeID, endNodeID; GraphNode[] rNodes; @@ -91,7 +90,7 @@ class Citizen extends Entity { i_age = age; i_diameter = 15; pathFinder = makePathFinder(gs, pathAlgorithm); - f_movementSpeed = random(0.1, 2); + f_movementSpeed = random(0.05, 1); rNodes = pathFinder.getRoute(); c_selected = color(128, 50, 50); @@ -115,20 +114,15 @@ class Citizen extends Entity { void update() { f_angle = v2_direction.heading(); + + turn(); + + if (b_moving) { //if rNodes.length > 0 move(); } - - watch(); - //look collision detection } - void lookAt (int x, int y, int prio) { - } - void watch() { - if (b_moving) { - } - } void goTo(int x, int y, int prio) { //add: go to node? go to house? int i_goToX = x; @@ -164,14 +158,12 @@ class Citizen extends Entity { if (rNodes.length > 0) { nextNode = 0; b_moving = true; - //for (int i = 0; i < rNodes.length; i++) { - // rNodesList.add(rNodes[i]); - //} } else { //implement more intelligent design which calls goTo not in this frame (this can cause infinite loops), but in the next 120 frames or so //also at this point i can move recalculating the nodes into the next frames if no route is found (not only random).. if (b_randomRun) goTo(int(random(0, pg_map.width)), int(random(0, pg_map.height)), 10); } } + void move() { if (rNodes.length > nextNode) { float f_xPosNext = rNodes[nextNode].xf(); @@ -182,8 +174,7 @@ class Citizen extends Entity { f_xPos += i_direction(f_xPosNext-f_xPos, f_movementVelo) * f_movementVelo; f_yPos += i_direction(f_yPosNext-f_yPos, f_movementVelo) * f_movementVelo; - v2_direction.x = f_xPos - f_xPosNext; - v2_direction.y = f_yPos - f_yPosNext; + turnTo(f_xPos-f_xPosNext, f_yPos-f_yPosNext, .3); if (abs(f_yPos - f_yPosNext) < f_movementVelo && abs(f_xPos - f_xPosNext) < f_movementVelo) { f_yPos = f_yPosNext; diff --git a/Entities.pde b/Entities.pde index 61939e6..d5274cb 100644 --- a/Entities.pde +++ b/Entities.pde @@ -1,6 +1,6 @@ int i_interactableAmount = 10; - //entitiy-subklassen: papier .. computer .. mobiles ... books ... lamps ... tables ... +//entitiy-subklassen: papier .. computer .. mobiles ... books ... lamps ... tables ... Interactable[] interactables = new Interactable[10]; @@ -22,6 +22,12 @@ class Entity { }; boolean b_selected; boolean b_moving; + boolean b_turning; + PVector v2_turnBuffer = new PVector(0, 0); + float f_turnSpeed; + + int i_turning; + float f_xPos, f_yPos, f_xSpawn, f_ySpawn; float f_angle; int i_diameter = 10; @@ -29,11 +35,7 @@ class Entity { color c_selected = color(128, 50, 50); color c_color = color(50, 200, 80); color c_stroke = color(255, 255, 255); - //PVector v2_direction(int x, int y){ - // PVector pv = new PVector(f_xPos+x,f_yPos+y); - // return (pv); - //}; - PVector v2_direction = new PVector(0,0); + PVector v2_direction = new PVector(0, 0); void spawn(int house) { //generic spawn PVector v2_spawnPoint = houses.get(house).v2_randomSpawnPoint(); @@ -41,24 +43,50 @@ class Entity { f_ySpawn = v2_spawnPoint.y; f_xPos = f_xSpawn; f_yPos = f_ySpawn; - v2_direction.x = f_xPos; - v2_direction.y = f_yPos + 10; + turnTo(0, 10, 0); f_angle = 0; b_linked = true; } + + + void spawn(int x, int y) { //specific spawn f_xSpawn = x; f_ySpawn = y; f_xPos = f_xSpawn; f_yPos = f_ySpawn; - v2_direction.x = f_xPos; - v2_direction.y = f_yPos + 10; + turnTo(0, 10, 0); b_linked = true; } void despawn() { b_linked = false; } - + + void turnTo(float x, float y, float speed) { + f_turnSpeed = speed; + if (f_turnSpeed > 0) { + b_turning = true; + v2_turnBuffer.x = x; + v2_turnBuffer.y = y; + float difference = v2_direction.heading() - v2_turnBuffer.heading(); + if (difference < -PI) difference += TWO_PI; + if (difference > PI) difference -= TWO_PI; + if (difference > 0.0) i_turning = -1; + if (difference < 0.0) i_turning = 1; + f_turnSpeed*=4*abs(difference); + } else { + v2_direction.x = x; + v2_direction.y = y; + } + } + void turn() { + if (!(abs(int(v2_direction.heading() * 1000) - int(v2_turnBuffer.heading()*1000)) < 100)) { + v2_direction = v2_direction.rotate(i_turning*PI/180*f_turnSpeed); + } else { + b_turning = false; + } + } + void display() { pg_map.stroke(c_stroke); pg_map.fill(c_color); diff --git a/Map.pde b/Map.pde index 775014d..8241147 100644 --- a/Map.pde +++ b/Map.pde @@ -11,8 +11,17 @@ int i_biggestHouseSize; ArrayList houses = new ArrayList(); - void initHouses() { + + s_map = new String[img_houses.height/i_sMapReso]; + + for (int y = 0; y < s_map.length; y++) { + s_map[y] = str('.'); //because += char on string delivers "null" as first stringentry in each arrayentry?! + for (int x = 0; x < img_houses.width/i_sMapReso; x++) { + s_map[y]+= '.'; + } + } + img_houses.loadPixels(); for (int x = 0; x < img_houses.width; x++) { for (int y = 0; y < img_houses.height; y++) { @@ -23,12 +32,23 @@ void initHouses() { } } } + img_houses.updatePixels(); for (House house : houses) { + //give houses their respective relative size (biggest house = 100) house.i_size = int(map(house.i_size, 0, i_biggestHouseSize, 0, 100)); + //create ascii map in s_map + for (PVector point : house.v2d_points) { //create ascii map in s_map + s_map[int(point.y/i_sMapReso)] = replaceCharAt_v1(s_map[int(point.y/i_sMapReso)], int(point.x/i_sMapReso), '#'); + } } } - +String replaceCharAt_v1(String s, int pos, char c) { + char[] ch = new char[s.length()]; + s.getChars(0, ch.length, ch, 0); + ch[pos] = c; + return new String(ch); +} class House { PVector v2_center; int i_size; diff --git a/Server.pde b/Server.pde new file mode 100644 index 0000000..8f3dc55 --- /dev/null +++ b/Server.pde @@ -0,0 +1,30 @@ + +String s_map[]; //send this via tcp +int i_sMapReso =1; //the higher the smaller the reso +void clientCommunication() { + client = server.available(); + if (client != null) { + s_fromClient = client.readString(); + if (s_fromClient.equals("give locx")) { + server.write(str(citizen[i_selectedCitizen].f_xPos/i_sMapReso)); + } + if (s_fromClient.equals("give locy")) { + server.write(str(citizen[i_selectedCitizen].f_yPos/i_sMapReso)); + } + if (s_fromClient.equals("give a")) { + server.write(str(citizen[i_selectedCitizen].f_angle)); + } + if (s_fromClient.equals("give mapw")) { + server.write(str(img_houses.width/i_sMapReso)); + } + if (s_fromClient.equals("give maph")) { + server.write(str(img_houses.height/i_sMapReso)); + } + if (i_mapLevelTransferC >= img_houses.height/i_sMapReso) i_mapLevelTransferC = 0; + if (s_fromClient.equals("give map")) { + server.write(s_map[i_mapLevelTransferC]); + //println(s_map[i_mapLevelTransferC]); + i_mapLevelTransferC++; + } + } +} diff --git a/UI.pde b/UI.pde index 18f8b53..f204109 100644 --- a/UI.pde +++ b/UI.pde @@ -1,5 +1,5 @@ -Button buttons[] = new Button[3]; +Button buttons[] = new Button[4]; int i_uiTransparency = 200; @@ -12,6 +12,7 @@ void initUI() { buttons[0] = new Button(15, 50, 100, i_debugTextSize, 5, "Autoplay", 0); buttons[1] = new Button(15, 70, 100, i_debugTextSize, 5, "Lock Camera", 1); buttons[2] = new Button(15, 90, 100, i_debugTextSize, 5, "Debug", 2); + buttons[3] = new Button(15, 110, 100, i_debugTextSize, 5, "Control Eyes", 3); } @@ -69,6 +70,7 @@ void drawUI() { "Angle: " + citizen[i_selectedCitizen].f_angle, "Movement speed: " + round(citizen[i_selectedCitizen].f_movementSpeed*100), "Random Run: " + citizen[i_selectedCitizen].b_randomRun, + "Turning: " + citizen[i_selectedCitizen].b_turning, " ", "Sunrise: " + S_sunrise, "Sunset: " + S_sunset, @@ -118,6 +120,7 @@ void buttonFunctions(int s) { } break; case(3): + b_controlEyeWithMouse = !b_controlEyeWithMouse; break; default: break; @@ -197,11 +200,14 @@ void mousePressed() { } } if (mouseButton == RIGHT) { + // if(citizen[i_selectedCitizen].hover){ + //} if (!b_autoPlayAfterSelect) { citizen[i_selectedCitizen].b_randomRun = false; citizen[i_selectedCitizen].b_moving = false; } citizen[i_selectedCitizen].goTo(constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width), constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height), 10); + citizen[i_selectedCitizen].turnTo(citizen[i_selectedCitizen].f_xPos-constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width), citizen[i_selectedCitizen].f_yPos-constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height),4); } } int i_mapViewToMap(int mouse, int offset) { diff --git a/citizen_server.pde b/citizen_server.pde new file mode 100644 index 0000000..761bd31 --- /dev/null +++ b/citizen_server.pde @@ -0,0 +1,124 @@ +import processing.net.*; + + +//settings +boolean b_smallerImage = false; //use a cropped, smaller version of the 1920x1080 image for faster development +boolean b_loadSun = false; //load sun from web-api instead of local json file (local file is adressed to january 4th 2019. might implement a check that downloads today's information only once... + + +boolean b_cameraFollow = true; +boolean b_autoPlayAfterSelect = false; + + +boolean b_controlEyeWithMouse; + + +boolean b_debug = true; +boolean b_drawNodes = false; + +float f_nodeResolution = 0.2; //defines density of path-finding nodes, multiplied with resolution +int i_pathAlgorithm = 3; +int i_debugTextSize = 10; +int i_mapW, i_mapH; +int i_windowW, i_windowH; +int i_viewportW, i_viewportH; + +//void mousePressed() { +// citizen[0].goTo(constrain(mouseX, 0, img_houses.width), constrain(mouseY, 0, img_houses.height)); +//} + +void spawnCitizen() { //happens after construction +} + +Server server; +Client client; + + +void setup() { + size(700, 600); + server = new Server(this, 5210); + //blendMode(MULTIPLY); + i_windowW = width; + i_windowH = height; + img_map = loadImage(dataPath("map/map.png")); + if (b_smallerImage) img_houses = loadImage(dataPath("map/houses_with_borders_small.png")); + else img_houses = loadImage(dataPath("map/houses_with_borders.png")); + img_streets = loadImage(dataPath("map/streets.png")); + + pg_map = createGraphics(img_houses.width, img_houses.height); + pg_map.beginDraw(); + //pg_map.blendMode(MULTIPLY); + pg_map.endDraw(); + + + surface.setResizable(true); + registerMethod("pre", this); + + i_mapW = pg_map.width; + i_mapH = pg_map.height; + + initHouses(); + initPathFinding(); + initWeather(); + initCitizen(); + initInteractables(); + initUI(); +} + +void pre() { + if (i_windowW != width || i_windowH != height) { + // Sketch window has resized + i_windowW = width; + i_windowH = height; + i_uiY = height - i_uiH; + i_uiW = width; + i_uiH = height - i_uiY; + } +} +String s_fromClient; +int i_mapLevelTransferC; +void draw() { + background(127); + clientCommunication(); + + pg_map.beginDraw(); + pg_map.background(127); + + if (b_debug) pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height); + else pg_map.image(img_map, 0, 0, img_houses.width, img_houses.height); + //pg_map.image(img_houses, 0, 0, img_houses.width, img_houses.height); + //image(img_streets, 0, 0, img_houses.width, img_houses.height); + + pg_map.fill(0); + pg_map.textSize(7); + pg_map.textAlign(CENTER); + //for (House house : houses) { + // house.display(); + //} + + if (b_drawNodes) drawNodes(); + + for (int i = 0; i < interactables.length; i++) { + interactables[i].update(); + interactables[i].display(); + } + + for (int i = 0; i < citizen.length; i++) { + if (citizen[i].b_linked) { + citizen[i].update(); + if (i != i_selectedCitizen) + citizen[i].display(); + if (b_debug) + citizen[i].debug(); + } + } + + if (b_controlEyeWithMouse) { + citizen[i_selectedCitizen].turnTo(citizen[i_selectedCitizen].f_xPos-(float)constrain(i_mapViewToMap(mouseX, i_mapOffsetX), 0, pg_map.width), citizen[i_selectedCitizen].f_yPos-(float)constrain(i_mapViewToMap(mouseY, i_mapOffsetY), 0, pg_map.height), 0) ; + } + citizen[i_selectedCitizen].display(); + + pg_map.endDraw(); + image(pg_map, i_mapOffsetX, i_mapOffsetY, i_mapW, i_mapH); + drawUI(); +} diff --git a/client/client b/client/client new file mode 100755 index 0000000000000000000000000000000000000000..e3fb1ac6b2c9024db18acce999bfe816b8c06bc8 GIT binary patch literal 77600 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 G{Qm{~ZiPDl literal 0 HcmV?d00001 diff --git a/client/main.cpp b/client/main.cpp new file mode 100644 index 0000000..3fcd6bf --- /dev/null +++ b/client/main.cpp @@ -0,0 +1,362 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#define PORT 5210 + +using namespace std; +using namespace std::chrono; + +string debugMsg; + +bool bGameLoop = true; +int nScreenWidth; +int nScreenHeight; +string screen; + +float fPlayerX = 8.0f; +float fPlayerY = 8.0f; +float fPlayerA = 0.0f; +float fElapsedTime; +bool bMoveForward; +bool bMoveBackwards; +bool bTurnLeft; +bool bTurnRight; + +void *keyListener(void *tid){ + long id = (long) tid; + initscr(); + noecho(); + //raw(); + //cbreak(); + //nodelay(stdscr, TRUE); + //scrollok(stdscr, TRUE); + //raw(); + int c; + while ((c = getch()) != ERR){ + debugMsg = ""; + debugMsg+=to_string(c); + switch (c) { + case 119: //w + bMoveForward = true; + break; + case 97: //a + bTurnLeft = true; + break; + case 115: //s + bMoveBackwards = true; + break; + case 100: //d + bTurnRight = true; + break; + default: + break; + } + } + endwin(); + pthread_exit(NULL); +} + +void writeStringToScreen(int x, int y, string text){ + int s = (y*nScreenWidth)+x; + for (int i = s; i < s+text.length(); i++){ + screen[i] = text[i-s]; + } +} + +int main(int argc, char const *argv[]){ + + //CLIENT STUFF + struct sockaddr_in address; + int sock = 0; + struct sockaddr_in serv_addr; + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Socket creation error \n");return -1; } + memset(&serv_addr, '0', sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(PORT); + if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0){ printf("\nInvalid address/ Address not supported \n"); return -1; } + if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ printf("\nConnection Failed \n"); return -1; } + + + + ///I HAVE TO LOOK INTO THIS MORE + struct termios ttystate; + tcgetattr(STDIN_FILENO, &ttystate); + ttystate.c_lflag &= (~ICANON & ~ECHO); //Not display character + ttystate.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); + /// + + //cInput = {'a','b'}; + //fputs("\e[?25h", stdout); //get cursor back /on signal abort ~ + //setterm(1); + pthread_t pThread[1]; + pthread_create(&pThread[0], NULL, keyListener, 0); + + struct winsize size; + ioctl(STDOUT_FILENO,TIOCGWINSZ,&size); + nScreenWidth = size.ws_col; + nScreenHeight = size.ws_row; + int nFrameRate = 60; + + + float fFOV = 3.14159 / 4.0; + float fDepth = 32.0f; + + char *mapwRequest = (char*)"give mapw"; + char bufferMapw[32] = {0}; + send(sock , mapwRequest , strlen(mapwRequest) , 0 ); + int getmapw = read( sock , bufferMapw, 32); + string s_MapWidth = ("%s\n",bufferMapw); + int nMapWidth = stoi(s_MapWidth); + + char *maphRequest = (char*)"give maph"; + char bufferMaph[32] = {0}; + send(sock , maphRequest , strlen(maphRequest) , 0 ); + int getmaph = read( sock , bufferMaph, 32); + string s_MapHeight = ("%s\n",bufferMaph); + int nMapHeight = stoi(s_MapHeight); + + + string map = ""; + + for (int i = 0; i < nMapHeight; i ++){ + char *mapRequest = (char*)"give map"; + char bufferMap[4096] = {0}; + send(sock , mapRequest , strlen(mapRequest) , 0 ); + int getmap = read( sock , bufferMap, 4096); + map += ("%s\n",bufferMap ); + } + /* + map += "################"; + map += "#..............#"; + map += "#####......#####"; + map += "#..............#"; + map += "#..........#####"; + map += "#..............#"; + map += "#####......#####"; + map += "#####......#####"; + map += "#####......#####"; + map += "#####......#####"; + map += "#####......#####"; + map += "#..............#"; + map += "#..............#"; + map += "#####......#####"; + map += "#..............#"; + map += "################"; */ + + system("kbdrate -d 250 -r 10"); + + + using clock = steady_clock; + auto tp1 = clock::now(); + auto tp2 = clock::now(); + + fputs("\e[?25l", stdout); //remove cursor*/ + + float fSpeedFactor = 20.0f; + + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + ////////BEGINDRAW///// + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////// + while(bGameLoop){ + + + tp2 = clock::now(); + duration elapsedTime = tp2 - tp1; + tp1 = tp2; + fElapsedTime = elapsedTime.count(); + + + //dynamic terminal window size (on Window Resize) + ioctl(STDOUT_FILENO,TIOCGWINSZ,&size); + nScreenWidth = size.ws_col; + nScreenHeight = size.ws_row; + screen.clear(); + screen.resize(nScreenWidth*nScreenHeight); + cout << "\x1B[0;0H"; //reset cursor to 0,0 + + + //fun part + + + + char *locxRequest = (char*)"give locx"; + char *locyRequest = (char*)"give locy"; + char *aRequest = (char*)"give a"; + + char buffer[32] = {0}; + + + + send(sock , locxRequest , strlen(locxRequest) , 0 ); + int getlocx = read( sock , buffer, 32); + string s_xPos = ("%s\n",buffer ); + + buffer[32] = {0}; + send(sock , locyRequest , strlen(locyRequest) , 0 ); + int getlocy = read( sock , buffer, 32); + string s_yPos = ("%s\n",buffer ); + + buffer[32] = {0}; + send(sock , aRequest , strlen(aRequest) , 0 ); + int geta = read( sock , buffer, 32); + string s_angle = ("%s\n",buffer ); + + + fPlayerA = stof(s_angle)+3.14159*0.5; + fPlayerX = stof(s_xPos); + fPlayerY = stof(s_yPos); + //this would be much better as class + if(bMoveForward){ + fPlayerX += fSpeedFactor*sinf(fPlayerA) * 5.0f * fElapsedTime; + fPlayerY += fSpeedFactor*cosf(fPlayerA) * 5.0f * fElapsedTime; + if(map[(int)fPlayerY * nMapWidth + (int)fPlayerX] == '#') + { + fPlayerX -= fSpeedFactor*sinf(fPlayerA) * 5.0f * fElapsedTime; + fPlayerY -= fSpeedFactor*cosf(fPlayerA) * 5.0f * fElapsedTime; + } + bMoveForward = false; + } + if(bMoveBackwards){ + fPlayerX -= fSpeedFactor*sinf(fPlayerA) * 5.0f * fElapsedTime; + fPlayerY -= fSpeedFactor*cosf(fPlayerA) * 5.0f * fElapsedTime; + if(map[(int)fPlayerY * nMapWidth + (int)fPlayerX] == '#') { + fPlayerX += fSpeedFactor*sinf(fPlayerA) * 5.0f * fElapsedTime; + fPlayerY += fSpeedFactor*cosf(fPlayerA) * 5.0f * fElapsedTime; + } + bMoveBackwards = false; + } + if(bTurnLeft){ + fPlayerA -= 0.15f; + bTurnLeft = false; + } + if(bTurnRight){ + fPlayerA += 0.15f; + bTurnRight = false; + } + + //shading part + for (int x = 0; x < nScreenWidth; x++){ + float fRayAngle = (fPlayerA - fFOV / 2.0f) + ((float)x / (float)nScreenWidth) * fFOV; + float fDistanceToWall = 0; + + bool bHitWall = false; + bool bBoundary = false; + + float fEyeX = -sinf(fRayAngle); + float fEyeY = cosf(fRayAngle); + + while(!bHitWall && fDistanceToWall < fDepth){ + fDistanceToWall += 0.1f; + + int nTestX = (int)(fPlayerX + fEyeX * fDistanceToWall); + int nTestY = (int)(fPlayerY + fEyeY * fDistanceToWall); + + if(nTestX < 0 || nTestX >= nMapWidth || nTestY < 0 || nTestY >= nMapHeight){ + bHitWall = true; + fDistanceToWall = fDepth; + } else { + if(map[nTestY * nMapWidth + nTestX] == '#') + { + bHitWall = true; + vector> p; //distance, dot + for (int tx = 0; tx < 2; tx++) + for (int ty = 0; ty < 2; ty++) + { + float vy = (float)nTestY + ty - fPlayerY; + float vx = (float)nTestX + tx - fPlayerX; + float d = sqrt(vx*vx + vy*vy); + float dot = (fEyeX * vx / d) + (fEyeY * vy / d); + p.push_back(make_pair(d,dot)); + } + + sort(p.begin(), p.end(), [](const pair &left, const pair &right) { return left.first < right.first; }); + + float fBound = 0.005; + if (acos(p.at(0).second) < fBound) bBoundary = true; + if (acos(p.at(1).second) < fBound) bBoundary = true; + if (acos(p.at(2).second) < fBound) bBoundary = true; + } + + } + } + + int nCeiling = (float)(nScreenHeight / 2.0) - nScreenHeight / ((float)fDistanceToWall); + int nFloor = nScreenHeight - nCeiling; + + short nShade = 32; + + + for(int y = 0; y < nScreenHeight; y++){ + if(y < nCeiling) + screen[y*nScreenWidth+x] = ' '; + if(y > nCeiling && y <= nFloor){ + if (fDistanceToWall <= fDepth / 4.0f) nShade = 77; //very close + else if (fDistanceToWall < fDepth / 3.5f) nShade = 72; + else if (fDistanceToWall < fDepth / 3.0f) nShade = 84; + else if (fDistanceToWall < fDepth / 2.5f) nShade = 73; + else if (fDistanceToWall < fDepth / 2.0f) nShade = 105; + else if (fDistanceToWall < fDepth / 1.5f) nShade = 58; + else if (fDistanceToWall < fDepth) nShade = 46; + else nShade = 32; // too far + if(bBoundary) nShade = '-'; + screen[y*nScreenWidth+x] = nShade; + } + else + { + float b = 1.0f - (((float)y - nScreenHeight / 2.0f) / ((float)nScreenHeight / 2.0f)); + if (b < 0.3) nShade = 32; //32 //very close + else if (b < 0.55) nShade = 96; //96 + else if (b < 0.8) nShade = 94; //94 + else if (b < 0.9) nShade = 42; //42 + else nShade = 32; //64 too far + screen[y*nScreenWidth+x] = nShade; + + } + } + } + + + + + + writeStringToScreen(0, nScreenHeight-3,"Received from server: " + s_xPos+ " "+s_yPos+ " "+s_angle + " " + to_string(nMapWidth)+ " " + to_string(nMapHeight) + " "); + + + //writeStringToScreen(0, 0, "Key pressed: " + to_string(123) + " Key code: " + to_string(cInput)); + //writeStringToScreen(0, nScreenHeight-3, debugMsg); + writeStringToScreen(0, nScreenHeight-2, "Frame rate: " + to_string(1.0f / fElapsedTime) + " "); + writeStringToScreen(0, nScreenHeight-1, "Key pressed: " + debugMsg + " Angle: " + to_string(fPlayerA) + " X: " + to_string(fPlayerX) + " Y: " + to_string(fPlayerY) + " "); + + //string sInput(1, cInput[0]); + + cout << screen; //this is the renderer + //cout << ; + + + tp1 += milliseconds(1000 / nFrameRate); + this_thread::sleep_until(tp1); + + } + return 0; +} diff --git a/data/server/map.txt b/data/server/map.txt new file mode 100644 index 0000000..2f4f9bb --- /dev/null +++ b/data/server/map.txt @@ -0,0 +1,270 @@ + #### ######## ## ###### ######### ###### + ## ######## ## #### # ######## #### + # ##### #### ## ### ##### ## ## + #### ### ###### ##### ### ##### + ##### ######## ######## ####### + ####### ######## ######## ##### + ####### # #### ###### ####### ### + ##### #### ###### #### #### # + ### ###### ###### # ### ## ## + # ####### ####### #### ##### + ######## ####### ##### ##### + ####### #### ### ##### ##### + # # #### ##### #### ### + ####### ##### ## #### ### +######### ##### #### ###### ######## +######### ##### ########## ###### ##### ########## +########## ##### ########## ###### ###### ### ########## +## ### ###### ###### ###### ###### ## ##### ########### + ###### ###### ###### #### ########### ######## + ## ### ## # # ################### # #### + ##### ## ### ########## ###### # ##### ## ########## + ##### #### #### ########## ### ###### #### ############## # + #### ##### # ## ######## # ###### ####### ########## ### ### #### + # ####### #### ###### ###### ###### ####### # ###### #### ###### + ##### ############# ###### ### ######## #### ###### ##### # ######## # + ### # ####### ### ###### ####### ###### ###### ##### ### ########## ### + ### ##### ######## #### ###### ######### ####### ### #### ##### ########## ##### + ###### ##### ####### ####### ###### ##################### ##### ###### ######## ####### + ######## ###### ## ####### # ######## ######## ################# ### #### ##### ##### ####### + ######## ##### ####### ####### ############## ################# ### ##### #### ### ####### ### ###### + ####### #### ####### ####### ############## ##### ###### #### ### ### ######## #### + ### ##### ####### ####### ####### ##### ######## ########## ### ########### ###### ## ### # + ## ##### ####### ######## ####### ############ ##### ## ####### ####### ##### + ######## ####### #### ##### ##### #### ### ### ###### ### ##### ###### ###### + ######## ###### ##### # #### ## ## ###### ##### #### #### #### ###### +# ######## ##### ##### #### #### #### ### ####### ##### ###### #### # ###### +## ####### ##### #### ##### ##### ####### # ######### ### ##### ######## ## ###### # ###### +## ### ##### #### ##### ###### ##### ######## ########## ###### ##### ####### ##### +## ## ##### #### ##### ###### ### ## ####### ########### ######## ###### #### #### ## + ##### ##### ##### ####### ##### #### ##### ## ######### ###### # ### ### ##### + ## ####### ##### ##### ### ###### ###### ## ############## #### #### # ##### + #### ########### ##### ##### ### ##### ###### # ###### ## ######## ### # ##### ###### #### + ###### ############ ##### ##### ###### ##### ### #### ####### #### ############ ####### ###### ####### + ## ###### ############# ##### #### ###### ##### ###### #### ######## ### ###### ########## ## ## ####### ## ###### ##### ####### + #### #### ############# ## ##### ##### ##### ###### ##### ####### ## ######### ######## ######## ##### ### ##### ### #### ###### #### ######### # ####### # + ####### ### ########## #### ##### ###### #### ##### ### ###### ############ ################### ##### ##### ### #### #### ##### ########### ###### ###### ##### + ####### # ######## ##### ##### ###### #### ##### ###### ### ############ ################### # ##### ## ### ##### ### ###### ########### ### # ####### ## ##### + ####### ### ##### ##### ###### ##### ## #### ###### ### ######## #################### ## ##### ## ##### #### ##### ###### #### ####### #### ##### + ####### ##### ### ### ##### ###### ##### ##### ### ####### ####### #### #################### #### ##### ###### #### ## ##### ###### #### ######## ####### ### + ######## ##### ##### ##### ###### #### ##### ##### ##### ######### ## ## ### #### ###### ######## ## ##### ##### #### #### ##### ######## ###### + ####### ### ######## ### ## #### ##### ## ##### ## ########### ################## ######### ####### # ### ## ## ###### #### ######## ### + ###### # ########## ###### ### #### ##### #### ##### ############# ###### ############### ### ## # ######### ######### ######## ###### ######## ## # + #### ############# ####### ###### ##### ##### ##### ############# ########## ################### #### ############# ############# ######### ##### ######## ##### ### #### # + ## ############## ####### ######## ##### #### ### ############ ############## ## ################### ################ ############### ########## ##### ### ######## #### ###### ### #### # + ############## ####### ######## ####### ###### ## #### ############ ############## #### ################## ################## ###### #### ############# #### ### ######## ###### #### ### #### # + ############## ####### ######## ####### ######## ###### ##### # ### ######## # #### #### ##### # ################ ###### ## ## ################ ### #### ######## ####### ## # ### ### # + ################ ####### ######### ####### ######## ### ##### ### ###### ### #### #### ###### ############ #### ################# #### ### ##### ######## ####### ##### ### ## # + ################## #### ######## ####### ######## ##### ###### ### ##### # ######## ###### # #### ################# ######## #### ###### ######## ###### ##### ### ### + ################### # ######### ####### ######## ### ######## #### ##### ######### # ### ####### ####### ############## ########### ### ############ ######## ## ##### #### ### ### + ################ #### ######### ####### ######## ####### ##### ##### ############# ################## ############ ## ########### ################ ######## ## #### ### ## + ########### ##### ######## ######## #### ### # #### ###### ############# ############ #### ##################### #### ########## ################ ################ ###### #### # + ######## ##### ######### ##### ## ##### ###### # ############## ############ #### ##################### # ######## ######## ########## ### ####### ##### # #### + ###### ##### ######### ##### #### ## ### ########### ############ #### ################### ##### # ######## ########## #### ###### ##### #### + ### ##### ######### ##### ##### ### ######### ############ #### ################## # #################### ##### ##### #### ### ### + ## ## #### #### ########### ############ #### ####### ############# ### #### ##### ### ### ## + ##### #### ##### ########## # #### ############### ### #### #### ### #### #### + ####### #### ######### ### ## # ########### # ###### # # ##### #### #### ####### + ####### ##### ######## ##### #### ## ######## ####### ######### ####### #### ##### ##### ######### + ###### ############# #### ######## #### ##### ##### ############# ####### ######### ####### ###### ### ##### ##### ######### + ### ############# ## ##### ######## ##### ######## ########### ############## ######## ######### ## #### ####### ###### ## #### ##### ######### + # ############# #### ### ####### ####### ######### ############ ############# ######## ## ## ### #### ###### #### ## ##### ######## ######## + ############# ###### #### ####### ######### ######## ############ ############# ######## ## ### ##### #### ###### ##### ##### ########## ###### + #### ######## ## ####### ####### ####### ######### ########## ########## ####### ### ## ##### ## ###### #### ##### #### ########## ### ### + #### ######## #### ######## #### ##### ######### ### ### ### #### ## ##### ###### #### ######## ### ### # + #### #### ## ##### ######### # ###### ####### ######## # #### ##### # ###### # ### ######### ### ### # + ### ##### ## ####### ######### ###### ######## ### #### #### # ##### #### ###### # ######### ##### ###### ### ## ## +### #### ########## ### ### ##### ######## ######### ##### ######## ### ##### ##### #### ## ####### ##### ### ############## ##### ### ### ### ## +### ###### ################ ### #### ######## ######### ###### ####### ###### # ### ### ######## ## ##### ############## ##### ## ##### ## +### ######### ############################## ######## ########## ### ##### ######## ######### ### ## ####### ######## ############## ##### ######## ######### ## + ########### ############################## ######## ########### ##### #### ##### ######## ######### #### ### #### ### ## ########## ############### ##### ######## ### ######### # + ############# ########################### ## #################### ###### #### ##### ######## ###### # ### #### #### #### ############ ######## ## ######## ### ######## # + ############### ## ############ #### ##################### ####### #### ## ########## ######## ### ##### #### # ############ ### ######## #### ####### # + ################# #### #### ####### ##################### ######### ## ########## ######### #### #### ######### #### #### ###### # + #################### ###### #### ######### #################### ##### #### ########## ######## # #### ###### ### #### ### #### ######### + ##################### ######### #### ########## ################# ### #### ## ###### ## ###### ##### #### # ####### #### ###### #### ##### ###### #### ######### + # ################## ######### #### ## ## ## ########## ######## ###### ########## ### ######### ####### ### ## #### ####### # ###### ##### #### ##### ###### ### ###### + #### ################# ### ######## ######## # ############# ######## # ## ######## ###### ######### ####### ## ############# ## ##### ##### #### ##### ###### + ###### ############### ##### ############# ####### ####### #### ########### ############ ######## ##### ########### ####### ############### #### ## # ##### ##### +######### ############ ################### ####### ####### ####### ######### ############## ##### #### ######### ####### ######## ####### ##### #### ##### ##### ####### +# ####### ############ ################## ##### ### ### ###### ####### ####### ######## ##### ######## # # ###### ######## ##### #### ###### ##### ## ######### +######## ############ ### ######################## ####### ### ####### ###### ######## #### ####### ##### ##### #### ######### #### ####### ###### ### #### ##### ### +## ### ########### ########################## ####### ####### #### ######## #### ################ ##### #### # ########## # ##### ## ###### ####### ### #### ######### +##### ############ ############################# #### ## ###### #### #### ## ########### ###### ###### ######## #### ##### ##### ######## ### ##### ######### +### ########### ############################## ## # ###### #### ###### ########## ###### ####### ########## ### ## ##### ## ######## ##### ####### ## ##### #### +### ######## ########################## #### ##### ### ######### ### ### ###### ################# ###### ### ##### ######### ##### #### ### ##### #### + # ###### #################### ######## #### ######### ### #### ### ################# ### ### ########### #### ######### ##### #### + ##### ############### ########## ##### ########### ####### ######## ### ################ ##### #### ### ########### ##### #### ######### ### #### #### + ## ##### ##### ############## ### ##### ######## ######## ######## ### ### ######## ###### #### ### ###### ### #### ##### ##### #### #### ## #### + ## ######### ############## #### #### ##### ###### ####### #### ### ### ### ## # ####### #### ### ### ### # ###### ### #### #### #### + ############## ########### ##### ### ##### ### ####### ### ### ##### ### ####### #### #### #### # ###### ### #### #### #### + ################### #### ######## #### ### # # ##### # ####### #### ### ##### ## ###### ### ###### ### #### ##### ### # #### #### + ##################### ###### ##### ##### ### #### ### ##### ##### ####### ### ###### ###### #### ###### #### ##### ## ###### ## ######## #### #### ### + #### ################## ######## ## ##### ##### ##### #### ####### ####### #### ######## ### #### #### ###### ##### ##### ### ############ ############# #### #### ### + ###### ############### ############ ### ###### ############# ## ########## ######## ########### ### ###### # ### #### ###### ##### ##### ###### ########### ### ####### ##### ### ##### + ######## ############ ###### ######## ### ###### #### ####### ############ ####### ####### ###### ######## ### ### ### # ##### ###### ############# ### ###### ###### ##### # + ####### ######### ######## #### #### ### ###### # ## ##### ############ ####### ######## ######### ######## ##### ### ### #### #### #### #### #################### ###### ###### #### #### #### ##### # + ###### ###### ### ###### ############ #### ## #### ### ##### ############ ############# ################## ############ ###### #### ####### ### ## ###################### ###### ## ###### #### ###### #### #### ##### # + ## ############### ####### #### ########### ## #### #### ##### ## ######## ### ####### ########## ######## ######## ###### ###### ### ######### #### ########### ######### ### ######### ##### ## #### ###### #### #### #### # + ######################## ####### ############## ### #### #### ###### ########### ######## ################### ########### ###### ###### ############### ### ##### ######## #### ### ### ######### ##### ### ### ###### #### ### + ## # ######################### ####### ############ ### ### #### ###### ############ ####### ################## ############## ####### ###### ############### ##### ##### ###### ### ## ### ######## ##### ### ### ###### + ###### #### ######################### ####### # # ######### ### ######## ###### ### ########### #### ########## ##### ## ################ ###### ###### ########## ###### ######## ## ## ### ##### # #### ### ######## ##### ### # + ###### ######## ##################### ####### ######### ####### ## ####### ######## ###### ########## ## # ############# ##### ####### ###### # ##### ############## ###### ######## #### # ### #### ###### ### ######### # ## + ###### ########### ######## # ####### ########### #### ###### ######### ####### ###### ##### ########## ####### ##### ###### #### ######## ###### ######## ##### ####### ###### ## ######## # ###### + ###### ############## # ###### ############## ### ##### ####### ####### ##### ####### ########## ####### #### ####### ##### ##### ##### # ###### ######## ############# ##### ### ## #### ##### ###### + ###### ################ ## ################# ## #### # ##### ######## ############# ########### ####### ##### ########## ##### ### ## #### ### ### ######### ############# ### ## #### #### #### # + ##### ################# ######## ########### #### #### ########### ############# #### ######### ## #### ############### #### ##### #### ###### ## ########## ############ ## # ####### #### #### #### + #### ################ #### ###### ### ###### ## ########### ############## ###### #### ######## ####### ############### ## ## ####### ##### ######## #### ######## ########### #### ############# ### #### + ### ################ ## ## ###### ### ## ### ####### ## ########### ############### ######## #### ################ ############## ###### ###### #### ########## ###### ######## ### ##### ##### #### ################# + #### ############# ##### ## #### ### ##### ####### ### ######### ### ######### ####### #### ############# ### ############ ######### ###### ############## ####### #### ## #### ##### #### #### ############# + ### ########## ###### ##### ### #### ###### # ####### ###### ###### ########### ####### ####### ######## ### ############ ########### ####### #### #### ###### ###### # ### #### #### # #### #### #### ####### # + ## ###### ###### ##### ######## ################ ######## ### ################## ######## ####### ######## ### ########## ########### ########### ####### # ####### #### ## ## ## #### ##### #### #### #### #### ### # +# ## ##### ####### ########### #### # ############## ########### ### ################## ################ ## ###### ######## ########### ########### #### ### # #### ###### ###### #### #### ###### #### #### ### #### ### # +# # # ###### ######### # #### # ### ###### #################### ###### ################# ################ ####### # ###### ########## ########## ############ ###### # ####### ##### ##### ###### #### ### #### ### ### # +## ###### ##### #### ## ### ####### ### ################## ####### ############# ### ################# ############## ### ### ####### ###### ############### ######## ###### ###### ##### ###### #### ### ### +## ### # ### ########### ###### ######## ### ################ ######## ###### ####### ############# ################# # #### ##### # ### ################ ########## ### ###### ###### ### ## + ###### #### ## #### ####### ######### ################ ### ####### #### ########## ############################### ###### ### ##### ############ # ############ ## # ###### # #### #### ### ## + ###### ###### ### ######## ######## ########### ##### ######## ######### ############################## ###### ####### ########### ############ #### ### ###### ### #### #### ###### + ####### ######## ####### ###### ##### #### ####### ##### ##### ########### ####### ## ###### ######## ############ ############## #### ###### ###### ##### #### #### ##### # + ###### ############ ###### ### ## ### #### ####### ## ## ############# #### ##### ###### ######## ############ ################ #### ####### ###### #### #### ## #### #### #### ###### ### + ###### ############# ### ##### ##### ######## ######## ########## #### ### ####### ###### ####### ####### ############### # ###### ###### ## #### #### ### ### ###### #### #### #### #### ### + ###### ############ #### ## ### #### ####### ############# ##### ####### ##### ######### ###### ####### ####### ################# ###### ###### ##### #### #### ##### ###### #### #### ### ### ## ### + ####### ########## ####### ##### ######## ########### ## ######## ############# ## ## ##### ######## ############ ###### ######## ##### ################# #### #### ##### #### ### #### ###### #### #### ###### + ####### ######### ####### ##### ######## ############ #### ###### ############## ###### ### ##### ## ###################### ######## # ################## # ## ## ##### #### ### #### ##### ### ### ## ### + ###### ###### ###### #### ####### ########### ###### ### ############## ######### ######## ############# #### ###### ####### ################## #### ## ### #### ### # ###### + ###### ##### ### ## ####### ########### ######## ############# ############# ####### ################# #### ##### ### ######## ################# ### ###### ### #### ## ### + ###### ## ####### ########### ## ######## #### ############## ################ ##### ################## ######## ############ ######### ## #### ###### #### ## ## + ###### ####### ############ ##### ########## ##### # ############## ################ ## ################## #### # ############# ######### #### # #### #### ### ### + #### ######## ########## ###### ########## ##### #### ############## ################ ### ################## #### ### ####### ## ####### ####### ## ###### #### ### ### + #### ### ######## ### ######### ## ###### ### #### ############# ############## ##### ############### ############## ##### ##### ### ###### ############ #### ## ### + #### ##### ######## #### ############# ##### ### #### ############## ######### ##### ####### #### # ########### ##### ##### #### ###### ## ############ #### ### + ###### ####### #### ############### ### ### #### ############## ###### ### ###### ###### ## #### ###### ####### #### #### ##### #### ############ #### #### ##### ## +# ##### ####### #### ################ ### #### #### ################# ## # ####### ##### ####### ## ###### ##### ########### ##### #### #### ###### ######## #### ######### ###### ##### +# #### ####### # ################ ####### ### #### ################ ##### ######## ##### ####### ##### ####### ## ############# #### #### ## ## ##### ## ## #### ######### ##### ### #### +## # ####### ############### ######## #### #### ################# ####### ######### ####### ############## ####### ########### #### ### ## #### ### #### ################# ## # #### +# ####### #### ##### #### ####### #### #### ################# ###### ######### ####### ############## ########## ############ ## #### ##### ## ##### ### # ################# # #### #### + # #### ##### ####### ##### #### ############ #### ######### ###### # ############# ######### #### #### ##### ###### ## ###### ### #### ################ #### + ## ## ### ##### ###### ###### #### #### ########### #### ######### ######## #### ############ ###### # ###### ###### #### #### #### #### ############### ##### #### + #### ## #### ########### ##### #### ##### ### ######## ##### # ################# ###### ########### ### ###### ### ###### ## ##### ### #### ######### ##### #### + ##### #### ##### ###### ### ### # ######### ##### ### #### #### ###### ################# ####### ########## #### # #### # # ####### ### #### ### #### ######### #### # + ### ###### ##### #### #### #### ##### ######## #### ##### ########## ##### #### ######### ######## ## ###### ########### ###### ### ### ### ###### #### #### #### ######### #### ##### + # ###### ### #### ## ## #### ######## #### ## ####### ### ### ########### ########### ###### ######## ############# ############ ####### ##### ##### #### ###### ######### ### #### + #### # #### ## ### ############ ############# ######### ########### ############ ####### ### ############## ## ###### ####### ###### ##### ## ## ##### ######### # #### + ## ####### ###### ###### ## ####### ####### ##################### ############ ####### ## # ###### ###### ### ##### ####### #### #### #### ### ######### #### #### + ####### ### ######## ## ## ### ## ################# #################### ############ ####### #### ### ############## ##### ###### ###### ## ## # ## ###### #### ######### #### ##### + ####### #### ######### ###### ### #### ########################### #### #### ##### ####### ############# ################## ###### ##### ## ####### #### ### ######## ######## ########## # #### ### + ## ## #### ###################### ######## ################## ### ########## ##### ####### ############ ##### ###### ###### ###### ######## ####### ### ##### ##### ######### ############# ######### ### ### + ###### #### ###################### ######## ################## ########## ###### ################## ###### ### ####### ######## ####### ###### ##### ###### ######### #### ################## #### ###### # + ###### ##### ### ############ ## ####### ################ #### ##### ### ###### ########## #### #### # ################ ####### ###### ### ##### ####### ####### ###################### #### ####### + ###### ######## #### ######## #### ########## ## ##### ######## ####### ########## # ######## ############### ### ###### # # ### ##### ################################ ### ###### + ### ## # ##### ##### #### ######## ## ########## #### ## ########### ####### ########## ####### ############# ### ##### ### ### ### ######################## ###### #### + ##### #### ### ###### #### ### ############# ## ######### ######## ############## ## ####### ### ####### ########## ###### ## ##### ##### #### #################### ##### ## + ####### ##### ##### ###### ####### #### ### ########## #### ####### ######## ############## #### ###### ####### ####### ####### ##### ###### ####### ############### ###### # +######## ### ####### ###### ######### #### ############ ##### ###### ####### ####### ########### ### ######## ### #### #### ######## ####### ##### # #### ####### ########### ###### ###### +####### ####### ###### ########### ##### ########### ## ######### ####### ######## ######## ##### ####### ### ###### ######## ##### ##### ### ## ##### ####### ##### ######## +###### ##### ##### ############ #### ############## ########### ####### ####### ##### ######## ## ######## ####### ######## ##### ##### ##### ### ####### ###### ######## +##### ## ### ### ##### ############ ##### ############## ########### ###### ######## ## ########## #### ######## ####### ######### # ## ###### ####### ## ########## ##### ### ######## +#### ###### ##### # ## ############ #### ############## ######## #### ####### ############# #### ####### ####### ######## ### # ##### ####### #### ########## ##### ###### #### +### ######## ####### ############ #### ############# ###### # # ##### ############### ### ##### ### ####### ######## #### #### ####### ###### ########## ### ####### +## ######## ####### ## ######## # ############### # #### #### ### ################### ### ### # ##### ####### ############# ###### ####### ######## ######### ####### +# # ######## #### ###### ###### #### ##### ### ######### ### #### ##### #################### ###### ######## ####### ########## ######## ## ####### ######### # #### ###### ###### + ### ######## ############ #### ###### ####### ## ####### ##### #### ######## #################### ###### ######### ####### ######### ######### #### ####### ########## #### #### ### ### #### + ##### ####### ############## ## ######## ## #### #### #### ######## ##### ########## #################### ###### ######## ####### ###### ######## ###### ##### ########## ###### #### ###### + ####### ######### ############### ######## #### #### ######## ### ########## #### ########## ################## ##### ### ### ####### ###### ######## ###### ### ######### ###### ##### ###### + ######### ########### # ################## ##### ###### # ##### ## ######## ############ ################ ################ # ### ####### #### ###### ####### # ####### ###### ####### ##### + ######## ############## ################### ## ### ####### ###### ##### #### ###### ############## ################# ## ############# ### ###### ### ######## ##### ###### ####### ##### + ######## ############### ################## ##### # ###### ###### ##### ## ####### #### ################# ################ ##### ########## ## #### ###### ### ## ## ####### ### ### ######## ##### ### + ###### ############## #################### ###### ### ###### ###### ################# ### ################### # ########### ####### ####### #### ## #### ##### ###### ##### # # ########### # #### ### + ####### ################################ ##### #### ##### ###### ######### ######## ##################### #### ##### ######## ##### ####### ### ### ##### ### ################# ## #### + ####### ############################# ## ### ############# ###### ################# # ##################### ### ##### ######## ## ######### #### ###### ## ################# + ####### ############################ ### ############## ###### ########## #### ### ########### ### ##### ##### ##### ####### ############ ## ######## ### ###### #### ################# + ####### ############################# ###### ############### ###### ######## # ###### ########### ##### ## ##### ##### ##### ############ ##### ########## ##### ##### ###### ################# + ####### ### ############################ ###### ############### ###### ######## ########## ####### ##### ##### ## ########## ###### ############ ##### ###### ######### ################# +###### ##### ########################## ###### ############## ### ############ #### # ####### ##### ##### ######## ######## ####### #### ##### ##### ## ########## ################## +##### ##### ######################### ### ############### ############## ##### ####### ##### ###### ##### ####### #### #### ##### ##### ###### #### ########## ##### +#### ##### ######################## # ############## ################# #### ## ####### ##### ######## ##### ###### # #### ##### ##### ## ##### ###### # ######## ## +### ##### ###################### ## ############## ######## ## #### ##### ##### ####### ############# ## ## ### #### ##### ##### #### #### ####### #### ###### #### ##### +## ##### ####################### #### ############# ##### ##### #### ###### ###### ########### ##### # # #### ##### ####### ###### ## ###### ###### #### ###### ###### + ##### ####################### ###### ############## ### #### ##### ###### ##### ######## ####### ### ##### #### ####### ###### ### ####### ## ######## ####### + ##### ##################### ####### ############## ### # ##### #### ####### ## ###### ######## ### ##### #### ####### ###### # ####### ####### ####### + ##### ################### ##### ############## ####### ####### ## ###### # ### ######## ##### #### ####### ##### ###### ###### ##### ### + ##### ################# ## ############ ###### ######### ###### ## ### # # ####### ###### ##### ####### ### ### ### #### #### # ###### + ##### ################ # ########## ####### ######## ################ #### ####### ##### ##### # ## ##### ##### ## ## ####### + ##### ############### ## #### ######## ## ###### ### ##### ############### ##### ##### ## ## #### ### ###### ##### ####### + ##### ############# ##### ###### ###### ##### ##### #### ############# ###### ###### #### ### ##### ###### ##### ##### # ###### + ####### ############ ###### ######## ### ####### # ## ## ########## # ###### ####### ###### ###### ## ### ######## # ### ### ### ### + ######### ##### ################## ## ####### ##### ### ######### #### ##### ###### ####### ########### ######## ### ## # ##### ### + ########## # ################# ####### ###### ### ########## ##### ##### # #### ## ####### ##### ###### ####### ###### #### ### ####### ###### ## + ######### ################## ###### ###### #### ######### ###### ###### #### ####### #### ##### # #### ## ### ###### #### ##### ###### ###### #### + ########## ################## ### #### # ### ########## ##### ###### ####### ####### ### ##### ###### ######## ###### ### ###### ### #### ### ##### + ########## # ############### ### # #### #### ## ########### # ##### ###### ######## ##### # ##### ### # ############ ####### # ###### #### ## ### ## ##### + ######### ## ################ #### ###### ### ################# ##### ## ## ###### ######### ### ### ## ####### ################ ####### #### ### ### #### #### + ########## ### ## ########### ######## ####### #### ################# ##### ### ######## ## ######## ##### ####### ########### #### ####### ## #### ## ##### ##### + ########## ##### ########### ########### ####### # ################## #### ###### ############ ######## ##### ###################### ###### ######## #### ##### # ##### + ######### ###### ########### ############# ###### ################## ## ####### ########## #### ##### ## ##### ###################### ###### ######## # ## ###### ### + ########## ####### ########### ############ #### ## ################## ###### ######### ### ### ##### ##### #################### ### ######## ### ###### #### +########## ####### ########### ########### # ##### ################## # ## ######### ### ## ###### #### ####### ## ###### # ####### ##### ##### #### +######## ####### ########### ###### ## ###### ################ #### ####### #### ####### ##### ## ###### ## # ###### ###### #### + ###### ###### ########### ### ### ### ####### ############## # ###### ##### ### # ####### #### ### ##### ##### ### + ##### ###### ########## ###### # ##### ####### ########## #### ###### ### ######## ####### # ###### ### #### ##### ###### + ###### ###### ########### ######## ######## ###### # ######### ##### ###### ####### ##### ######## ###### #### ####### + ##### ################# ####### ######### #### #### ####### ######## ###### ######## ### ######## ###### ### ### ###### #### + ###### ############## #### ########## # ###### ## ## ########## ###### ########## ###### ######### ###### # ### ####### + ###### ########### ## ######### ######## ########### #### ############ #### ########### ############### ####### + ###### ###### # ########## ### #### ############# # ############ ## # ########### ##### ############## + ##### ###### ######### ## ###### ################ ########## #### ########### ###################### # + ## ###### ####### ######## ########### ##### # ####### ### ######## ############# ############ ###### #### ## + #### #### ## ######### # ########### ####### ##### #### ########### #### ####### ########## ##### ##### ###### ##### + ### ## ### ##### ####### ### ########## ####### ## ##### ########### # ######### ####### ### ###### ###### ####### ###### + ####### #### ###### ###### ###### ######## ###### ### ## ############ ########## ### ### ##### ###### ##### ####### ###### + ############## ####### ###### ### ######## ###### ###### #### ## ##### ##### ########### ### ##### ### ###### ###### ##### ####### ## #### + ## # ############### ####### ##### # ######## #### ##### ####### ##### #### ##### ############ ######## ##### ###### ## ##### ##### #### ## + ######################### ## ##### # ## ######## # #### ######### ###### ############ ######### ######## ####### ##### ### ##### ###### ####### + ########################## ### ### #### ######### # ########## ####### ########### ##### ### ### ######## ###### ###### ### ###### ###### ###### + ############### ######## ###### ##### ####### ############# ####### ########### # ##### ### ## ######## ###### ####### ###### ##### ## ###### #### + ############ ########## ######## ###### ###### ## ############# ####### ############## #### ## #### ## #### ####### ##### ###### ## ###### ## ## ##### ##### #### + ########## ######### ########## ##### ###### #### ############# # ####### ###### ###### ########### ###### #### ###### ##### ### ###### ##### ###### ##### #### + ######## ######## ############ ##### ###### #### ############# ### ####### ### ####### ########### ### ####### ## ### # ## ##### ### ###### ###### ##### #### + ######## ###### ############## #### ###### ##### ############# ##### ####### ####### ########## #### ####### ### ###### ##### ##### ###### ## #### ##### #### + ######## ###### ################ ## # ########### ### ############## ######## ####### ####### ########## ####### ###### #### #### ##### ##### #### ###### # #### + ####### ###### ########## ######## ##### ## ########### #### ## ########## ######### ####### ###### #### ### ######## #### ##### ##### ## ### ##### ## ###### #### + ##### ###### ########## ######## ###### #### ########## ## #### ### ####### ######### ####### ##### ###### ## ###### ### ##### ## ##### ### ##### #### + ### ########### ######### ####### ## # ###### ###### ####### ######## ###### ####### ######## #### ### #### ###### ## ###### ## ###### ## + ########## ####### ####### #### ### ####### ### ####### ##### #### # ### ##### ######### ## ##### ## ### ##### ### ##### # ##### # ###### + # ########## ####### # ###### ##### ###### ###### ###### ###### ### ## ##### ## ## ######### ### ####### ##### ## #### ###### ### ##### #### ####### + ############# ##### ### #### ## ##### ####### ###### ####### #### ##### ## ##### ######### ## ##### ####### ####### ##### ###### ### ## ## ###### #### + ############# #### ##### # #### ## ######### ##### ####### ## ####### ####### ######### #### ##### ##### ####### ###### ### ### ###### ##### ## + ############# #### ######## ##### ######### ## ####### ######### ###### ## ## ##### ### ###### #### ## ###### ### ##### ######## ### # ## + # ########## ############ ###### ####### ##### ########### ### #### #### ###### ##### #### #### # ##### ############ ###### ### ######## ### #### + ## #### ########## ########## # #### ##### ### ### ########### ##### ## ##### ####### ##### ### ## ####### ######### ###### #### # #### #### #### + ########## ######### ######## #### # ## ### ## ##### # ########## ##### ############# ##### ### ####### ######## ##### #### ### ## ## #### ### ## + ############ ####### ##### ##### ##### # ### ####### ### #### ######### #### ############# ##### ###### #### ###### # ### # ##### ##### ## ### # ###### + ############ #### ###### ###### ###### ###### ##### #### ######## ## ############# ##### #### #### ##### ### ##### ###### ###### #### ###### + ############ ## ##### ######## ############# ####### ### ####### ########### ##### ## ## ## ### ## ##### ##### ##### ##### ### ##### ##### ## +############# ### ### ######## ####### #### ####### # ## ########## ##### # ###### ## ## ##### ####### ##### ## #### ##### ### ## ##### ##### +############ ##### ######## ######### ####### ### ############### ### #### ###### #### #### ####### ## ### ##### #### ##### # ##### ### ## ###### +######## ### ###### ######## ##### ##### ########### ######### ###### ##### #### ##### ####### ##### ########## ### ### #### #### # ##### ###### + #### #### ###### ####### # ### # ### ########## ######## ## ###### #### ###### ########### ##### ## #### ##### ## #### # ### ###### #### + # ##### ###### ## ######## #### # ### ### ########## ## #### ##### ###### #### ######## ## ###### ##### ## #### # #### ###### ######## ## + #### ####### #### ######## ##### ##### ##### ######### ## ####### ### # ############# ###### ##### ### ##### ###### # ########## + ### # ###### ###### ######## ### #### ##### ###### ##### ########## # ### ############### ##### ## ## ## #### ####### #### ########## + #### ## ############# ######## ### ##### #### ##### #### ########## ##### ### ####### ### ## ### ### # ##### # ##### ###### ######### + # ##### ### ############ ######## #### ##### ## #### ## ########## ##### ## ######## ###### ##### #### ### # ### ##### ## ###### ######## ### + ### #### ##### ########### ######## ##### #### ## ########## #### ###### ##### ###### ### ###### ### #### ##### ### ###### ##### #### + #### # ###### ######## ######## ######### ## #### ##### ### ## ##### ### ##### ###### # ## ##### ##### #### ##### ## #### ### ##### +# ##### #### ###### ######## #### ## #### ###### ####### ###### #### ### ### ##### ###### ### ######## #### ##### #### ##### #### ## # ## # ###### +# ### ### ## #### ####### #### ##### ## ####### ### # ###### ###### ######## ####### ##### ## ######### ##### #### ## ##### ##### ##### #### ### ##### # +# ##### ## ## ###### ### ### ####### #### ######## ##### ### ####### ##### ######## ####### ##### ######### #### # ###### ##### ## ##### #### ###### ## ## +# ####### #### ### # ###### ####### ##### ####### ##### ##### ######### ## ### ######## ####### ###### # ######## ## ##### ##### ##### #### #### ### ###### ## # + ####### #### ## # ### ####### ## ###### #### ####### #### ###### ########## ##### ## ### ######### ########## #### ### ##### ####### ### ## ##### #### ##### + ##### ##### ##### ##### ######### #### ##### #### #### ### ##### ########## ###### ## ######### #### ##### ## ### ####### ####### ## ###### + ## ### ## ####### # ############## ##### ### ##### ## ### ### ########## ##### ########## ## ###### #### ######## ###### ####### + #### ##### ######## #### ############ # #### ###### ##### # ########## ##### ########## ######## ###### ###### ##### ##### + ### #### ##### ######### ##### ########## #### ##### ## ##### ######### ##### ########### ####### ###### # #### ## ### + ######### #### ##### ######### ######## ####### ###### ### #### ## ##### ######## ###### ## ####### ##### #### ### # + ############## ## #### ######### ########## ####### ###### # # ######## #### ## #### ## ### #### ##### ## ####### ### ## #### + ################### ## ### ## # ######### ########### ####### ##### ### ### ##### ###### #### # #### ## ## ### #### ####### #### + ##################### #### #### ### ####### ############ ###### ## ###### ##### ### ###### #### #### ### #### # ##### # ####### # ## + ##################### ##### #### ###### ###### ########### ####### ######## ####### # ## ###### ### #### #### ###### ########## ###### #### + ###################### ##### # ######## ### ############ ####### ## ####### ###### #### ##### ## ### ## ### ####### ########## ##### ##### + ###################### ### ######### # ########### ###### ##### ###### #### ###### ## #### # #### ## ##### ########## ###### #####