From 59e33fbe928fe64f1d061da198140e72c5c36492 Mon Sep 17 00:00:00 2001 From: Hopp Date: Fri, 1 Apr 2022 13:15:38 -0400 Subject: [PATCH 1/7] moved files from assignment 2 --- 2517597.jpg | Bin 0 -> 54684 bytes Kirby.png | Bin 0 -> 13578 bytes RoboCat/Chapter3.vcxproj | 20 +- RoboCat/Colour.cpp | 32 ++ RoboCat/Colour.h | 43 +++ RoboCat/GraphicsLibrary.cpp | 126 ++++++ RoboCat/GraphicsLibrary.h | 67 ++++ RoboCat/Inc/RoboCatShared.h | 6 - RoboCat/InputSystem.cpp | 136 +++++++ RoboCat/InputSystem.h | 68 ++++ RoboCat/Src/Main.cpp | 361 +++++++++++++++++- allegro_wrapper_functions-main/Colour.cpp | 32 ++ allegro_wrapper_functions-main/Colour.h | 43 +++ .../GraphicsLibrary.cpp | 130 +++++++ .../GraphicsLibrary.h | 68 ++++ .../InputSystem.cpp | 159 ++++++++ allegro_wrapper_functions-main/InputSystem.h | 76 ++++ allegro_wrapper_functions-main/LICENSE | 21 + allegro_wrapper_functions-main/README.md | 43 +++ coin.png | Bin 0 -> 2536 bytes homie.png | Bin 0 -> 16363 bytes tomato.png | Bin 0 -> 2381 bytes 22 files changed, 1414 insertions(+), 17 deletions(-) create mode 100644 2517597.jpg create mode 100644 Kirby.png create mode 100644 RoboCat/Colour.cpp create mode 100644 RoboCat/Colour.h create mode 100644 RoboCat/GraphicsLibrary.cpp create mode 100644 RoboCat/GraphicsLibrary.h create mode 100644 RoboCat/InputSystem.cpp create mode 100644 RoboCat/InputSystem.h create mode 100644 allegro_wrapper_functions-main/Colour.cpp create mode 100644 allegro_wrapper_functions-main/Colour.h create mode 100644 allegro_wrapper_functions-main/GraphicsLibrary.cpp create mode 100644 allegro_wrapper_functions-main/GraphicsLibrary.h create mode 100644 allegro_wrapper_functions-main/InputSystem.cpp create mode 100644 allegro_wrapper_functions-main/InputSystem.h create mode 100644 allegro_wrapper_functions-main/LICENSE create mode 100644 allegro_wrapper_functions-main/README.md create mode 100644 coin.png create mode 100644 homie.png create mode 100644 tomato.png diff --git a/2517597.jpg b/2517597.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ebaa86efe6945fefbd851f42db913117a62c5b53 GIT binary patch literal 54684 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 Q9smFU07*qoM6N<$f_J^;tpET3 literal 0 HcmV?d00001 diff --git a/RoboCat/Chapter3.vcxproj b/RoboCat/Chapter3.vcxproj index 8c859a81..5b18b0b9 100644 --- a/RoboCat/Chapter3.vcxproj +++ b/RoboCat/Chapter3.vcxproj @@ -92,6 +92,9 @@ true true Bin\$(Configuration)\ + true + true + true true @@ -128,7 +131,7 @@ ProgramDatabase EnableFastChecks ..\SDL\include;Inc;..\ - Use + NotUsing RoboCatPCH.h @@ -370,10 +373,10 @@ - + + + - - @@ -385,12 +388,10 @@ - - - - - + + + @@ -405,7 +406,6 @@ Create RoboCatPCH.h - diff --git a/RoboCat/Colour.cpp b/RoboCat/Colour.cpp new file mode 100644 index 00000000..7a5ef3d1 --- /dev/null +++ b/RoboCat/Colour.cpp @@ -0,0 +1,32 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +Colour.cpp +*/ + +#include "Colour.h" +#include "RoboCatPCH.h" + +//Constructor - without alpha +Colour::Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b) +{ + mR = r; + mG = g; + mB = b; + mA = 255; +} + +//Constructor - with alpha +Colour::Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, unsigned __int8 a) +{ + mR = r; + mG = g; + mB = b; + mA = a; +} + +//Destructor +Colour::~Colour() +{ + +} \ No newline at end of file diff --git a/RoboCat/Colour.h b/RoboCat/Colour.h new file mode 100644 index 00000000..216b028c --- /dev/null +++ b/RoboCat/Colour.h @@ -0,0 +1,43 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +Colour.h + + File information: + This file contains data used for colours. +*/ + +class Colour +{ + //-------------------------Private data------------------------- + + //Red channel + unsigned __int8 mR; + + //Green channel + unsigned __int8 mG; + + //Blue channel + unsigned __int8 mB; + + //Alpha channel + unsigned __int8 mA; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b); + Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, unsigned __int8 a); + + //Destructor + ~Colour(); + + //Accessor(s) + unsigned __int8 getR() { return mR; }; + unsigned __int8 getG() { return mG; }; + unsigned __int8 getB() { return mB; }; + unsigned __int8 getA() { return mA; }; +}; diff --git a/RoboCat/GraphicsLibrary.cpp b/RoboCat/GraphicsLibrary.cpp new file mode 100644 index 00000000..ea5254d6 --- /dev/null +++ b/RoboCat/GraphicsLibrary.cpp @@ -0,0 +1,126 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +GraphicsLibrary.cpp +*/ + +#include "GraphicsLibrary.h" +#include "RoboCatPCH.h" + +#include +#include + +//Constructor +GraphicsLibrary::GraphicsLibrary(float screenSizeX, float screenSizeY) +{ + //Setup data - screen size + mScreenSizeX = screenSizeX; + mScreenSizeY = screenSizeY; + + //Allegro display + mpDisplay = nullptr; +} + +//Destructor +GraphicsLibrary::~GraphicsLibrary() +{ + //Delete bitmaps + std::vector>::iterator iterator; + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + al_destroy_bitmap(iterator->second); + } + mBitmapPointersVector.clear(); + + //Clean up display + al_destroy_display(mpDisplay); + mpDisplay = nullptr; +} + +bool GraphicsLibrary::init(std::string backgroundFilePath) +{ + //Init allegro + if (!al_init()) + { + std::cout << "error initting Allegro\n"; + system("pause"); + return false; + } + + //Init image addon + if (!al_init_image_addon()) + { + std::cout << "error initting image add-on\n"; + system("pause"); + return false; + } + + //Init font add on + if (!al_init_font_addon()) + { + std::cout << "error initting font add-on\n"; + system("pause"); + return false; + } + + //Init ttf add on + if (!al_init_ttf_addon()) + { + std::cout << "error initting ttf add-on\n"; + system("pause"); + return false; + } + + //Setup display + mpDisplay = al_create_display(mScreenSizeX, mScreenSizeY); + + if (mpDisplay == nullptr) + { + return false; + } + + return true; +} + +void GraphicsLibrary::render() +{ + //Flip display buffers + al_flip_display(); +} + +void GraphicsLibrary::loadImage(std::string imageFilePath, std::string imageIdentifier) +{ + //Add the name of the image and the loaded bitmap to the vector of pairs + mBitmapPointersVector.push_back(std::make_pair(imageIdentifier, al_load_bitmap(imageFilePath.c_str()))); +} + +void GraphicsLibrary::drawImage(std::string imageIdentifier, float posX, float posY) +{ + //Find the image and draw if it exists + std::vector>::iterator iterator; + + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + if (iterator->first == imageIdentifier) + { + al_draw_bitmap(iterator->second, posX, posY, 0); + } + } +} + +void GraphicsLibrary::drawTintedImage(std::string imageIdentifier, float posX, float posY, Colour col) +{ + //Find the image and draw if it exists + std::vector>::iterator iterator; + + //Set colour + ALLEGRO_COLOR colour = al_map_rgba(col.getR(), col.getG(), col.getB(), col.getA()); + + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + if (iterator->first == imageIdentifier) + { + al_draw_tinted_bitmap(iterator->second, colour, posX, posY, 0); + } + } +} \ No newline at end of file diff --git a/RoboCat/GraphicsLibrary.h b/RoboCat/GraphicsLibrary.h new file mode 100644 index 00000000..a8a9519c --- /dev/null +++ b/RoboCat/GraphicsLibrary.h @@ -0,0 +1,67 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +GraphicsLibrary.h + + File information: + This file contains function abstractions from Allegro 5, wrapped up in my Graphics Library. This will + be used to render images and text to the screen. + + Source I am consulting: Allegro 5.0.10 Manual - http://cdn.allegro.cc/file/library/allegro/5.0.10/allegro-5.0.10-manual.pdf +*/ + +#include +#include + +#include "Colour.h" + +//https://github.com/liballeg/allegro_wiki/wiki/Allegro-in-Visual-Studio#using-nuget-within-visual-studio +#include +#include +#include +#include +#include +#include + +class GraphicsLibrary +{ + //-------------------------Private data------------------------- + + //Screen data + float mScreenSizeX; + float mScreenSizeY; + + //Allegro display + ALLEGRO_DISPLAY* mpDisplay; + + //Other images to draw + std::vector> mBitmapPointersVector; + + friend class InputSystem; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + GraphicsLibrary(float screenSizeX, float screenSizeY); + + //Destructor + ~GraphicsLibrary(); + + //Accessor(s) + float getScreenSizeX() { return mScreenSizeX; }; + float getScreenSizeY() { return mScreenSizeY; }; + + //Mutator(s) + + //Functions + bool init(std::string backgroundFilePath); + void render(); + void loadImage(std::string imageFilePath, std::string imageIdentifier); + + //Drawing functions + void drawImage(std::string imageIdentifier, float posX, float posY); + void drawTintedImage(std::string imageIdentifier, float posX, float posY, Colour col); +}; \ No newline at end of file diff --git a/RoboCat/Inc/RoboCatShared.h b/RoboCat/Inc/RoboCatShared.h index d7eac1bc..bc232e1f 100644 --- a/RoboCat/Inc/RoboCatShared.h +++ b/RoboCat/Inc/RoboCatShared.h @@ -51,15 +51,10 @@ class GameObject; #include "RoboMath.h" -#include "TransmissionData.h" -#include "InFlightPacket.h" - #include "LinkingContext.h" #include "ByteSwap.h" #include "MemoryBitStream.h" -#include "AckRange.h" -#include "Timing.h" #include "StringUtils.h" #include "SocketAddress.h" #include "SocketAddressFactory.h" @@ -67,4 +62,3 @@ class GameObject; #include "TCPSocket.h" #include "SocketUtil.h" #include "OutputWindow.h" -#include "DeliveryNotificationManager.h" diff --git a/RoboCat/InputSystem.cpp b/RoboCat/InputSystem.cpp new file mode 100644 index 00000000..3ab059ec --- /dev/null +++ b/RoboCat/InputSystem.cpp @@ -0,0 +1,136 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +InputSystem.cpp +*/ + +#include "InputSystem.h" +#include "RoboCatPCH.h" + +#include + +//Constructor +InputSystem::InputSystem() +{ + //Create an event queue + mpEventQueue = al_create_event_queue(); +} + +//Destructor +InputSystem::~InputSystem() +{ + //Cleanup event queue + al_destroy_event_queue(mpEventQueue); + mpEventQueue = nullptr; +} + +float InputSystem::getMouseX() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return mouseState.x; +} + +float InputSystem::getMouseY() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return mouseState.y; +} + +std::pair InputSystem::getMousePosition() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return std::make_pair(mouseState.x, mouseState.y); +} + +//Init +bool InputSystem::init(GraphicsLibrary* pGraphicsLib) +{ + //Init keyboard + if (!al_install_keyboard()) + { + std::cout << "error installing Allegro keyboard plugin\n"; + system("pause"); + return false; + } + + //Init mouse + if (!al_install_mouse()) + { + std::cout << "error installing Allegro mouse plugin\n"; + system("pause"); + return false; + } + + //Register screen event source + al_register_event_source(mpEventQueue, al_get_display_event_source(pGraphicsLib->mpDisplay)); + + //Register keyboard event source + al_register_event_source(mpEventQueue, al_get_keyboard_event_source()); + + //Register mouse event source + al_register_event_source(mpEventQueue, al_get_mouse_event_source()); + + return true; +} + +MouseButton InputSystem::getMouseInput() +{ + //If there is an event + al_wait_for_event(mpEventQueue, &mEvent); + + if (mEvent.type == InputMode::MouseDown) + { + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + //Check the button pressed + if (mouseState.buttons & 1) //Left mouse held + { + return MouseButton::LeftMouse; + } + else if (mouseState.buttons & 2) //Right mouse held + { + return MouseButton::RightMouse; + } + else if (mouseState.buttons & 4) //Middle mouse held + { + return MouseButton::MiddleMouse; + } + } +} + +KeyCode InputSystem::getKeyboardInput() +{ + //If there is an event + al_wait_for_event(mpEventQueue, &mEvent); + + if (mEvent.type == InputMode::KeyPressed) + { + //Check the type + switch (mEvent.keyboard.keycode) + { + case KeyCode::Escape: + return KeyCode::Escape; + break; + + case KeyCode::R: + return KeyCode::R; + break; + + default: + /*return KeyCode::NONE*/; + } + } + + //return KeyCode::NONE; +} \ No newline at end of file diff --git a/RoboCat/InputSystem.h b/RoboCat/InputSystem.h new file mode 100644 index 00000000..3a69029e --- /dev/null +++ b/RoboCat/InputSystem.h @@ -0,0 +1,68 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +InputSystem.h + + File information: + This file contains the keycodes for input, which can be used in any way desired by other classes + and files. +*/ + +#include "GraphicsLibrary.h" + +//Include allegro libraries for input +#include + +enum KeyCode +{ + Escape = ALLEGRO_KEY_ESCAPE, + R = ALLEGRO_KEY_R +}; + +enum MouseButton +{ + LeftMouse = 0, + RightMouse = 1, + MiddleMouse = 2 +}; + +enum InputMode +{ + NONE = -1, + KeyPressed = ALLEGRO_EVENT_KEY_DOWN, + KeyReleased = ALLEGRO_EVENT_KEY_UP, + MouseDown = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN, + MouseUp = ALLEGRO_EVENT_MOUSE_BUTTON_UP +}; + +class InputSystem +{ + //-------------------------Private data------------------------- + + //Event queue + ALLEGRO_EVENT_QUEUE* mpEventQueue; + + //Event + ALLEGRO_EVENT mEvent; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + InputSystem(); + + //Destructor + ~InputSystem(); + + //Accessor(s) + float getMouseX(); + float getMouseY(); + std::pair getMousePosition(); + + //Functions + bool init(GraphicsLibrary* pGraphicsLib); + MouseButton getMouseInput(); + KeyCode getKeyboardInput(); +}; \ No newline at end of file diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 3b0ac9de..7cde36ff 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -1,8 +1,347 @@ #include "RoboCatPCH.h" +#include "allegro_wrapper_functions-main/GraphicsLibrary.h" +#include "allegro_wrapper_functions-main/Colour.h" +#include "allegro_wrapper_functions-main/InputSystem.h" + +#include +#include +#include + +using namespace std; #if _WIN32 +enum PacketTypes +{ + CREATE, + UPDATE, + DESTROY, + HELLO +}; + +enum ObjectTypes +{ + PLAYER, + COIN, + TOMATO +}; + +UDPSocketPtr CreateBoundSocket(std::string IP) +{ + UDPSocketPtr cliSock = SocketUtil::CreateUDPSocket(SocketAddressFamily::INET); + SocketAddressPtr cliAddr = SocketAddressFactory::CreateIPv4FromString(IP); + if (cliAddr == nullptr) + { + SocketUtil::ReportError("Create Client Socket"); + ExitProcess(1); + } + cliSock->Bind(*cliAddr); + return cliSock; +} + +class PlayerGameObject +{ + private: + int xPos; + int yPos; + string imageName; + bool isPlayer1; + public: + PlayerGameObject(int x, int y, string fileName, bool isPlayer) + { + xPos = x; + yPos = y; + imageName = fileName; + isPlayer1 = isPlayer; + }; + int getX() { return xPos; }; + int getY() { return yPos; }; + void Update(int keyPress) + { + if (isPlayer1) + { + switch (keyPress) + { + case KeyCode::P1_Down: + yPos += 7; + break; + case KeyCode::P1_Left: + xPos -= 7; + break; + case KeyCode::P1_Right: + xPos += 7; + break; + case KeyCode::P1_Up: + yPos -= 7; + break; + } + } + else + { + switch (keyPress) + { + case KeyCode::P2_Down: + yPos += 3; + break; + case KeyCode::P2_Left: + xPos -= 3; + break; + case KeyCode::P2_Right: + xPos += 3; + break; + case KeyCode::P2_Up: + yPos -= 3; + break; + } + } + }; + string getImageName() { return imageName; }; + void setX(int x) { xPos = x; }; + void setY(int y) { yPos = y; }; +}; + +class CoinObject +{ + private: + int xPos, yPos; + public: + CoinObject(int x, int y) { xPos = x; yPos = y; }; + int getX() { return xPos; }; + int getY() { return yPos; }; +}; + +class TomatoObject +{ + private: + int xPos, yPos; + public: + TomatoObject(int x, int y) { xPos = x; yPos = y; }; + int getX() { return xPos; }; + int getY() { return yPos; }; + void Update() { xPos--; }; +}; + +class GameState +{ + private: + bool isServer; + UDPSocketPtr sock; + SocketAddress otherAddr; + GraphicsLibrary* mLibrary; + InputSystem* mInputSystem; + PlayerGameObject* mPlayer; + PlayerGameObject* otherPlayer; + vector vCoins; + TomatoObject* tomato; + public: + GameState(bool serverState, string ourAddr, string other) + { + isServer = serverState; + sock = CreateBoundSocket(ourAddr); + sock->SetNonBlockingMode(true); + otherAddr = *(SocketAddressFactory::CreateIPv4FromString(other)); + cout << otherAddr.ToString() << endl; + mLibrary = new GraphicsLibrary(800, 600); + mLibrary->init("../2517597.jpg"); + mInputSystem = new InputSystem(); + mInputSystem->init(mLibrary); + if (isServer) + { + mLibrary->loadImage("../kirby.png", "Player"); + mLibrary->loadImage("../homie.png", "Other Player"); + mPlayer = new PlayerGameObject(650, 100, "../kirby.png", isServer); + otherPlayer = new PlayerGameObject(100, 100, "../homie.png", isServer); + } + else + { + mLibrary->loadImage("../kirby.png", "Other Player"); + mLibrary->loadImage("../homie.png", "Player"); + otherPlayer = new PlayerGameObject(650, 100, "../kirby.png", isServer); + mPlayer = new PlayerGameObject(100, 100, "../homie.png", isServer); + } + } + ~GameState() + { + delete mLibrary; + } + void Update() + { + mLibrary->loadImage("../2517597.jpg", "background"); + mLibrary->loadImage("../coin.png", "coin"); + mLibrary->loadImage("../tomato.png", "tomato"); + mLibrary->drawImage("background", 0, 0); + mLibrary->drawImage("Player", mPlayer->getX(), mPlayer->getY()); + mLibrary->drawImage("Other Player", otherPlayer->getX(), otherPlayer->getY()); + if (isServer) + { + tomato = new TomatoObject(800, rand() % 540 + 20); + for (int i = 0; i < 10; i++) + vCoins.push_back(new CoinObject(rand() % 700 + 50, rand() % 500 + 50)); + } + else + { + tomato = new TomatoObject(800, 800); + SendPacket(sock, &otherAddr, PacketTypes::HELLO, 1, 1, 1); + } + mLibrary->render(); + bool escapePressed = false; + + while (!escapePressed) + { + if (isServer) + { + tomato->Update(); + SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::TOMATO, tomato->getX(), tomato->getY()); + CheckForCollisions(mPlayer); + CheckForCollisions(otherPlayer); + } + else + { + ReceivePacket(sock, &otherAddr, mInputSystem); + } + SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::PLAYER, mPlayer->getX(), mPlayer->getY()); + ReceivePacket(sock, &otherAddr, mInputSystem); + for (auto& coin : vCoins) + { + mLibrary->drawImage("coin", coin->getX(), coin->getY()); + } + mLibrary->drawImage("tomato", tomato->getX(), tomato->getY()); + int keyPress = mInputSystem->getKeyboardInput(); + mPlayer->Update(keyPress); + mLibrary->drawImage("Player", mPlayer->getX(), mPlayer->getY()); + mLibrary->drawImage("Other Player", otherPlayer->getX(), otherPlayer->getY()); + if (keyPress == KeyCode::KeyEscape) + escapePressed = true; + + mLibrary->render(); + mLibrary->drawImage("background", 0, 0); + } + } + void SendPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, + int pos_x, int pos_y) + { + int packet[25]; + packet[0] = packetType; + packet[1] = objectType; + packet[2] = pos_x; + packet[3] = pos_y; + + char* bytePacket = (char*)packet; + + int bytesSent = ptr->SendTo(bytePacket, 100, *addr); + if (bytesSent <= 0) + { + SocketUtil::ReportError("Client SendTo"); + } + } + void SendCoinPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, vector coins) + { + int packet[25]; + packet[0] = packetType; + packet[1] = objectType; + for (int i = 2; i < 20; i += 2) + { + packet[i] = coins[i / 2 - 1]->getX(); + packet[i + 1] = coins[i / 2 - 1]->getY(); + } + + char* bytePacket = (char*)packet; + + int bytesSent = ptr->SendTo(bytePacket, 100, *addr); + if (bytesSent <= 0) + { + SocketUtil::ReportError("Client SendTo"); + } + } + void ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr, InputSystem* mInputSystem) + { + char buffer[100]; + { + int bytesReceived = ptr->ReceiveFrom(buffer, 100, *addr); + if (bytesReceived < 0) + { + SocketUtil::ReportError("Error receiving packet"); + } + else if (bytesReceived == 0) + return; + else + { + int* packet = (int*)buffer; + switch (packet[0]) + { + case PacketTypes::UPDATE: + { + switch (packet[1]) + { + case ObjectTypes::PLAYER: + { + otherPlayer->setX(packet[2]); + otherPlayer->setY(packet[3]); + break; + } + case ObjectTypes::COIN: + { + vCoins.clear(); + for (int i = 2; i < 20; i += 2) + { + vCoins.push_back(new CoinObject(packet[i], packet[i + 1])); + } + break; + } + case ObjectTypes::TOMATO: + { + tomato = new TomatoObject(packet[2], packet[3]); + break; + } + } + break; + } + case PacketTypes::HELLO: + { + SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); + break; + } + } + } + } + } + + void CheckForCollisions(PlayerGameObject* player) + { + for (vector::iterator it = vCoins.begin(); it < vCoins.end(); it++) + { + CoinObject* coin = *it; + if (((player->getX() < coin->getX() && player->getX() + 100 > coin->getX())//top left corner + && (player->getY() < coin->getY() && player->getY() + 100 > coin->getY())) + || ((player->getX() < coin->getX() + 50 && player->getX() + 100 > coin->getX() + 50)//bottom right + && (player->getY() < coin->getY() + 50 && player->getY() + 100 > coin->getY() + 50)) + || ((player->getX() < coin->getX() + 50 && player->getX() + 100 > coin->getX() + 50)//top right + && (player->getY() < coin->getY() && player->getY() + 100 > coin->getY())) + || ((player->getX() < coin->getX() && player->getX() + 100 > coin->getX())//bottom left + && (player->getY() < coin->getY() + 50 && player->getY() + 100 > coin->getY() + 50))) + { + vCoins.erase(it); + delete coin; + vCoins.push_back(new CoinObject(rand() % 700 + 50, rand() % 500 + 50)); + SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); + break; + } + } + if (((player->getX() < tomato->getX() && player->getX() + 100 > tomato->getX())//top left corner + && (player->getY() < tomato->getY() && player->getY() + 100 > tomato->getY())) + || ((player->getX() < tomato->getX() + 30 && player->getX() + 100 > tomato->getX() + 30)//bottom right + && (player->getY() < tomato->getY() + 30 && player->getY() + 100 > tomato->getY() + 30)) + || ((player->getX() < tomato->getX() + 30 && player->getX() + 100 > tomato->getX() + 30)//top right + && (player->getY() < tomato->getY() && player->getY() + 100 > tomato->getY())) + || ((player->getX() < tomato->getX() && player->getX() + 100 > tomato->getX())//bottom left + && (player->getY() < tomato->getY() + 30 && player->getY() + 100 > tomato->getY() + 30)) + || tomato->getX() <= 0) + { + tomato = new TomatoObject(800, rand() % 540 + 20); + } + } +}; int main(int argc, const char** argv) { @@ -16,10 +355,30 @@ int main(int argc, const char** argv) __argc = argc; __argv = argv; #endif - + srand(time(NULL)); SocketUtil::StaticInit(); + //DoThreadExample(); + GameState* state; + + bool isServer = StringUtils::GetCommandLineArg(1) == "server"; + + if (isServer) + { + state = new GameState(true, "localhost:9000", "localhost:9001"); + } + else + { + state = new GameState(false, "localhost:9001", "localhost:9000"); + } + + state->Update(); + + //cin.get(); + SocketUtil::CleanUp(); + delete state; + return 0; } diff --git a/allegro_wrapper_functions-main/Colour.cpp b/allegro_wrapper_functions-main/Colour.cpp new file mode 100644 index 00000000..7a5ef3d1 --- /dev/null +++ b/allegro_wrapper_functions-main/Colour.cpp @@ -0,0 +1,32 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +Colour.cpp +*/ + +#include "Colour.h" +#include "RoboCatPCH.h" + +//Constructor - without alpha +Colour::Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b) +{ + mR = r; + mG = g; + mB = b; + mA = 255; +} + +//Constructor - with alpha +Colour::Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, unsigned __int8 a) +{ + mR = r; + mG = g; + mB = b; + mA = a; +} + +//Destructor +Colour::~Colour() +{ + +} \ No newline at end of file diff --git a/allegro_wrapper_functions-main/Colour.h b/allegro_wrapper_functions-main/Colour.h new file mode 100644 index 00000000..216b028c --- /dev/null +++ b/allegro_wrapper_functions-main/Colour.h @@ -0,0 +1,43 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +Colour.h + + File information: + This file contains data used for colours. +*/ + +class Colour +{ + //-------------------------Private data------------------------- + + //Red channel + unsigned __int8 mR; + + //Green channel + unsigned __int8 mG; + + //Blue channel + unsigned __int8 mB; + + //Alpha channel + unsigned __int8 mA; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b); + Colour(unsigned __int8 r, unsigned __int8 g, unsigned __int8 b, unsigned __int8 a); + + //Destructor + ~Colour(); + + //Accessor(s) + unsigned __int8 getR() { return mR; }; + unsigned __int8 getG() { return mG; }; + unsigned __int8 getB() { return mB; }; + unsigned __int8 getA() { return mA; }; +}; diff --git a/allegro_wrapper_functions-main/GraphicsLibrary.cpp b/allegro_wrapper_functions-main/GraphicsLibrary.cpp new file mode 100644 index 00000000..a821e87c --- /dev/null +++ b/allegro_wrapper_functions-main/GraphicsLibrary.cpp @@ -0,0 +1,130 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +GraphicsLibrary.cpp +*/ + +#include "GraphicsLibrary.h" +#include "RoboCatPCH.h" + +#include +#include + +GraphicsLibrary::GraphicsLibrary() +{ +} + +//Constructor +GraphicsLibrary::GraphicsLibrary(float screenSizeX, float screenSizeY) +{ + //Setup data - screen size + mScreenSizeX = screenSizeX; + mScreenSizeY = screenSizeY; + + //Allegro display + mpDisplay = nullptr; +} + +//Destructor +GraphicsLibrary::~GraphicsLibrary() +{ + //Delete bitmaps + std::vector>::iterator iterator; + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + al_destroy_bitmap(iterator->second); + } + mBitmapPointersVector.clear(); + + //Clean up display + al_destroy_display(mpDisplay); + mpDisplay = nullptr; +} + +bool GraphicsLibrary::init(std::string backgroundFilePath) +{ + //Init allegro + if (!al_init()) + { + std::cout << "error initting Allegro\n"; + system("pause"); + return false; + } + + //Init image addon + if (!al_init_image_addon()) + { + std::cout << "error initting image add-on\n"; + system("pause"); + return false; + } + + //Init font add on + if (!al_init_font_addon()) + { + std::cout << "error initting font add-on\n"; + system("pause"); + return false; + } + + //Init ttf add on + if (!al_init_ttf_addon()) + { + std::cout << "error initting ttf add-on\n"; + system("pause"); + return false; + } + + //Setup display + mpDisplay = al_create_display(mScreenSizeX, mScreenSizeY); + + if (mpDisplay == nullptr) + { + return false; + } + + return true; +} + +void GraphicsLibrary::render() +{ + //Flip display buffers + al_flip_display(); +} + +void GraphicsLibrary::loadImage(std::string imageFilePath, std::string imageIdentifier) +{ + //Add the name of the image and the loaded bitmap to the vector of pairs + mBitmapPointersVector.push_back(std::make_pair(imageIdentifier, al_load_bitmap(imageFilePath.c_str()))); +} + +void GraphicsLibrary::drawImage(std::string imageIdentifier, float posX, float posY) +{ + //Find the image and draw if it exists + std::vector>::iterator iterator; + + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + if (iterator->first == imageIdentifier) + { + al_draw_bitmap(iterator->second, posX, posY, 0); + } + } +} + +void GraphicsLibrary::drawTintedImage(std::string imageIdentifier, float posX, float posY, Colour col) +{ + //Find the image and draw if it exists + std::vector>::iterator iterator; + + //Set colour + ALLEGRO_COLOR colour = al_map_rgba(col.getR(), col.getG(), col.getB(), col.getA()); + + for (iterator = mBitmapPointersVector.begin(); iterator != mBitmapPointersVector.end(); ++iterator) + { + if (iterator->first == imageIdentifier) + { + al_draw_tinted_bitmap(iterator->second, colour, posX, posY, 0); + } + } +} \ No newline at end of file diff --git a/allegro_wrapper_functions-main/GraphicsLibrary.h b/allegro_wrapper_functions-main/GraphicsLibrary.h new file mode 100644 index 00000000..0af35805 --- /dev/null +++ b/allegro_wrapper_functions-main/GraphicsLibrary.h @@ -0,0 +1,68 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +GraphicsLibrary.h + + File information: + This file contains function abstractions from Allegro 5, wrapped up in my Graphics Library. This will + be used to render images and text to the screen. + + Source I am consulting: Allegro 5.0.10 Manual - http://cdn.allegro.cc/file/library/allegro/5.0.10/allegro-5.0.10-manual.pdf +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Colour.h" + +//https://github.com/liballeg/allegro_wiki/wiki/Allegro-in-Visual-Studio#using-nuget-within-visual-studio + +class GraphicsLibrary +{ + //-------------------------Private data------------------------- + + //Screen data + float mScreenSizeX; + float mScreenSizeY; + + //Allegro display + ALLEGRO_DISPLAY* mpDisplay; + + //Other images to draw + std::vector> mBitmapPointersVector; + + friend class InputSystem; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + GraphicsLibrary(); + GraphicsLibrary(float screenSizeX, float screenSizeY); + + //Destructor + ~GraphicsLibrary(); + + //Accessor(s) + float getScreenSizeX() { return mScreenSizeX; }; + float getScreenSizeY() { return mScreenSizeY; }; + + //Mutator(s) + + //Functions + bool init(std::string backgroundFilePath); + void render(); + void loadImage(std::string imageFilePath, std::string imageIdentifier); + + //Drawing functions + void drawImage(std::string imageIdentifier, float posX, float posY); + void drawTintedImage(std::string imageIdentifier, float posX, float posY, Colour col); +}; \ No newline at end of file diff --git a/allegro_wrapper_functions-main/InputSystem.cpp b/allegro_wrapper_functions-main/InputSystem.cpp new file mode 100644 index 00000000..bb262445 --- /dev/null +++ b/allegro_wrapper_functions-main/InputSystem.cpp @@ -0,0 +1,159 @@ +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +InputSystem.cpp +*/ + +#include "InputSystem.h" +#include "RoboCatPCH.h" + +#include + +//Constructor +InputSystem::InputSystem() +{ + //Create an event queue + mpEventQueue = al_create_event_queue(); +} + +//Destructor +InputSystem::~InputSystem() +{ + //Cleanup event queue + al_destroy_event_queue(mpEventQueue); + mpEventQueue = nullptr; +} + +float InputSystem::getMouseX() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return mouseState.x; +} + +float InputSystem::getMouseY() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return mouseState.y; +} + +std::pair InputSystem::getMousePosition() +{ + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + return std::make_pair(mouseState.x, mouseState.y); +} + +//Init +bool InputSystem::init(GraphicsLibrary* pGraphicsLib) +{ + //Init keyboard + if (!al_install_keyboard()) + { + std::cout << "error installing Allegro keyboard plugin\n"; + system("pause"); + return false; + } + + //Init mouse + if (!al_install_mouse()) + { + std::cout << "error installing Allegro mouse plugin\n"; + system("pause"); + return false; + } + + //Register screen event source + al_register_event_source(mpEventQueue, al_get_display_event_source(pGraphicsLib->mpDisplay)); + + //Register keyboard event source + al_register_event_source(mpEventQueue, al_get_keyboard_event_source()); + + //Register mouse event source + al_register_event_source(mpEventQueue, al_get_mouse_event_source()); + + return true; +} + +MouseButton InputSystem::getMouseInput() +{ + //If there is an event + al_get_next_event(mpEventQueue, &mEvent); + + if (mEvent.type == InputMode::MouseDown) + { + //Update mouse state + ALLEGRO_MOUSE_STATE mouseState; + al_get_mouse_state(&mouseState); + + //Check the button pressed + if (mouseState.buttons & 1) //Left mouse held + { + return MouseButton::LeftMouse; + } + else if (mouseState.buttons & 2) //Right mouse held + { + return MouseButton::RightMouse; + } + else if (mouseState.buttons & 4) //Middle mouse held + { + return MouseButton::MiddleMouse; + } + } +} + +KeyCode InputSystem::getKeyboardInput() +{ + //If there is an event + al_get_next_event(mpEventQueue, &mEvent); + + if (mEvent.type == InputMode::KeyPressed) + { + //Check the type + switch (mEvent.keyboard.keycode) + { + case KeyCode::KeyEscape: + return KeyCode::KeyEscape; + break; + + case KeyCode::R: + return KeyCode::R; + break; + case KeyCode::P1_Down: + return KeyCode::P1_Down; + break; + case KeyCode::P1_Left: + return KeyCode::P1_Left; + break; + case KeyCode::P1_Right: + return KeyCode::P1_Right; + break; + case KeyCode::P1_Up: + return KeyCode::P1_Up; + break; + case KeyCode::P2_Down: + return KeyCode::P2_Down; + break; + case KeyCode::P2_Left: + return KeyCode::P2_Left; + break; + case KeyCode::P2_Right: + return KeyCode::P2_Right; + break; + case KeyCode::P2_Up: + return KeyCode::P2_Up; + break; + default: + /*return KeyCode::NONE*/; + } + } + + //return KeyCode::NONE; +} \ No newline at end of file diff --git a/allegro_wrapper_functions-main/InputSystem.h b/allegro_wrapper_functions-main/InputSystem.h new file mode 100644 index 00000000..f46e8f3c --- /dev/null +++ b/allegro_wrapper_functions-main/InputSystem.h @@ -0,0 +1,76 @@ +#pragma once + +/* +Allegro Wrapper Functions +Written by Adel Talhouk in FA21 +InputSystem.h + + File information: + This file contains the keycodes for input, which can be used in any way desired by other classes + and files. +*/ + +#include "GraphicsLibrary.h" + +//Include allegro libraries for input +#include + +enum KeyCode +{ + KeyEscape = ALLEGRO_KEY_ESCAPE, + R = ALLEGRO_KEY_R, + P1_Left = ALLEGRO_KEY_A, + P2_Left = ALLEGRO_KEY_J, + P1_Down = ALLEGRO_KEY_S, + P2_Down = ALLEGRO_KEY_K, + P1_Up = ALLEGRO_KEY_W, + P2_Up = ALLEGRO_KEY_I, + P1_Right = ALLEGRO_KEY_D, + P2_Right = ALLEGRO_KEY_L +}; + +enum MouseButton +{ + LeftMouse = 0, + RightMouse = 1, + MiddleMouse = 2 +}; + +enum InputMode +{ + NONE = -1, + KeyPressed = ALLEGRO_EVENT_KEY_DOWN, + KeyReleased = ALLEGRO_EVENT_KEY_UP, + MouseDown = ALLEGRO_EVENT_MOUSE_BUTTON_DOWN, + MouseUp = ALLEGRO_EVENT_MOUSE_BUTTON_UP +}; + +class InputSystem +{ + //-------------------------Private data------------------------- + + //Event queue + ALLEGRO_EVENT_QUEUE* mpEventQueue; + + //Event + ALLEGRO_EVENT mEvent; + + //-------------------------Public data------------------------- +public: + + //Constructor(s) + InputSystem(); + + //Destructor + ~InputSystem(); + + //Accessor(s) + float getMouseX(); + float getMouseY(); + std::pair getMousePosition(); + + //Functions + bool init(GraphicsLibrary* pGraphicsLib); + MouseButton getMouseInput(); + KeyCode getKeyboardInput(); +}; \ No newline at end of file diff --git a/allegro_wrapper_functions-main/LICENSE b/allegro_wrapper_functions-main/LICENSE new file mode 100644 index 00000000..52e8a5fb --- /dev/null +++ b/allegro_wrapper_functions-main/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Adel Talhouk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/allegro_wrapper_functions-main/README.md b/allegro_wrapper_functions-main/README.md new file mode 100644 index 00000000..e8462238 --- /dev/null +++ b/allegro_wrapper_functions-main/README.md @@ -0,0 +1,43 @@ +# allegro_wrapper_functions +Some Allegro 5 wrapper functions for C++ + +I wrote some code for my Computer Architecture final project in FA21 that allowed me to use abstracted Allegro 5 functions. Feel free to use this code, but please keep the block comment in each file :) + +EXAMPLE INIT FUNCTION IN MAIN.CPP: + +```cpp +//-------------------------Graphics Data------------------------- +GraphicsLibrary* pGraphics; +float screenSizeX = 1600.0; +float screenSizeY = 900.0; + +//-------------------------Input Data------------------------- +InputSystem* pInput; + +//-------------------------Assets------------------------- +const std::string ASSET_PATH = "..\\Assets\\"; +const std::string BACKGROUND_IMAGE_FILE = "Background_Image.jpg"; + +//-------------------------Asset Identifiers------------------------- +const std::string backgroundImageSprite = "background_image_image"; + +bool init() +{ + bool bSuccessfulInit = false; + + //Setup the graphical window + pGraphics = new GraphicsLibrary(screenSizeX, screenSizeY); + bSuccessfulInit = pGraphics->init(ASSET_PATH + BACKGROUND_IMAGE_FILE); + + //Add images to the graphcis library + pGraphics->loadImage(ASSET_PATH + BACKGROUND_IMAGE_FILE, backgroundImageSprite); + + //Setup the input system + pInput = new InputSystem(); + if (bSuccessfulInit) + bSuccessfulInit = pInput->init(pGraphics); + + //Init and return if it succeeded or not + return bSuccessfulInit; +} +``` diff --git a/coin.png b/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..b8da8e4159ae764dcf5509b50aa21aa61e3ed248 GIT binary patch literal 2536 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 tf0s5!2qA000RTNkl!O)+t)5Xsa`HlxnTC zI*Nkg*jCgcty1cRk%oJqkPvPS{G$W7WCz(&Hu-szND7VoWC4dR9;5)v z0C_|H`gwC3<{cce4kA)A-ds05p>C29&B7*k89v!t>a^~*{dm?)A; zk);?zlF7C@QDm7sTOK3H0Kw=edPo}8g2-F~#c7ZD3Vj4a0kRY?9$OZ=MJJ&Mgq$L( zM=&w}ub}e(LJbPk0`e%}{1+=D z^_HGDFti9w?zwcuy4+8Me!Amm)~O|o0p}n;>Ipa|+qLe%U@7~cFj4n;sG_GqcO+b8 zw&{C&-R+BwvXt!Wa*s%1Aq9&g9wgKj$L`LyLhr zP>#wh7%Cx{jMC-_LLo2$-*hf}dSU4`8)jC_PAw|CcD%;kxPz@{-~8oX&;HwusQ1Lo zoyLquQdQhKr<`Q2!Tbxu9Q_!kwZNA7RWz=goXLiWfO)lC*gwd+SI_Z>#sren!mx2==2;TX}nZbq(1 za;wM1th1GLs?)j~)~}oWdCvhN2~D1;ao6bsWEGT=*!IS&t{q$M&MwaZi-PHNVLGjJ zw4TFWluym78$j3*ku*3A!vP3|kcNk0Xb^oYLc1n&CN7cVvQgw#kz#`3Pz3vmyWXw2 zf9>)}sGo|OE5^b4Kp%nqd+$qaSpQOqX#uAbGb;-M0i?P*q&0U!RRy%4L-h25$Aw5g z8ytd`14xDmOO}FFg+05ubnG~t1w~k71v!->nM%^9>Qq1W^K~`NH*Itlm5d*!ks-fh z?5(#qc>5wStRseXq`!9{*ESK|^dfr{AG=Nu5V*1#Y0kB9qzh?Shfhx+OC+KNgcb z*&^3r7t?RPNu2EJ5@Nv(q6<~DJBmfCQXpEKx#GQo9I^lTjq4^1B!1%5jRYg;Q3H|& zlGz8heT%If$JqJUrrtsjH=9 z=PsUoV+-7|0u>!OZXy|greldD7(LOpbONk(_e?cq3sE!eE@^)eP*%k0-fny@cSaRm z*O^>jPsfLQc>S}F;NS-w4Eovq+;5mMr4Cb)&<%sC;z?XM)j`0f;=m5V$n4>C4^R~g zMz6nS0-T6Ny}F_>hRG<#xc)8&VNF9-6b!>am?nmxwA0QF(oo!Su(L$)zk#o zEXeDQ83~fIK}>=mkTP{d%D^zpjKQZfO2c&oHkXU-ue?Hke?K;-BLhq;Vy3MYkx@n$ z0>dI@^vj4Xfnubv<>mEHfR)QC4~<$NWrd_72&Z2*46Le3DwV=C#($c=PuDRG^5x`U zQB_RCz)0zt05cuVFi|WPRAG`#CNYpP6@g-vK{9dG*0fH5eT|LpYUM>lRTE7yiKc@| zYB()+5{X162t`qdMk0)c!^rX%-Bgm$Vll$u5oA@#1gGmM>@GJpT_>i6k!&ieDp0Kw zYH1w9nJL_%A~uO5AE>z*0C!w#`N)mEKr_@W=?a-1cp}IXU?IdNYB< zHH}~}$k%RJj>qF69*?8NG+Z7Ju2_tOF^X(gQEh3-HQd)-v(Gns&aVFq0sO zP9tLD)5P=?s0MmPE~QWYVoh$-{6D8I4e|8zo5!1k*4d7%$XE;VIs56~mY@37Gw+y( zj^m38N><#;P+cwg#U)4|eMH}m_n5itdc4ieaQ-}PFKouWZ~?iGJVHAK zjvvEPR!FM4guJysx~F7u^OlsqH?tY-HI3uo)WwsTbC@=Qk(5bK$BD|&C%fN|?)ms~ zm}TK2`$@>GNlS--rV!{#mjE? z)=urnl1+?w3?v!bzrl$MCo{UIN7{kjK4QYe;;=H>d3tH=__6hg_O>fUe?LkjifX3a z$%>*X$dZJTwubZ|Ckb#kP>PFD>l=>PW;Z_NsIGtC7}Zb_cnk9pdMabcwwgI#8gHd^ zKr+cd5LvU3T~)W+SJ$xH7!6E{^z|;$2mA}o;HBwiBvfW567I|g4trE_XZKoi^4e_0 zW&0c@WqVX_UJs^>5eT7=MzHvNUyK}I*#-Oye=}ZKOM!Ja00000NkvXXu0mjfmX?&Q literal 0 HcmV?d00001 From 1a8e3109743f76a7b997608f6c5eddbc01492868 Mon Sep 17 00:00:00 2001 From: Hopp Date: Tue, 5 Apr 2022 13:58:01 -0400 Subject: [PATCH 2/7] added timer, packets are sometimes dropped --- RoboCat/Src/Main.cpp | 163 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 143 insertions(+), 20 deletions(-) diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 7cde36ff..9bd29248 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -1,4 +1,3 @@ - #include "RoboCatPCH.h" #include "allegro_wrapper_functions-main/GraphicsLibrary.h" #include "allegro_wrapper_functions-main/Colour.h" @@ -7,6 +6,7 @@ #include #include #include +#include using namespace std; @@ -82,16 +82,16 @@ class PlayerGameObject switch (keyPress) { case KeyCode::P2_Down: - yPos += 3; + yPos += 7; break; case KeyCode::P2_Left: - xPos -= 3; + xPos -= 7; break; case KeyCode::P2_Right: - xPos += 3; + xPos += 7; break; case KeyCode::P2_Up: - yPos -= 3; + yPos -= 7; break; } } @@ -115,11 +115,129 @@ class TomatoObject { private: int xPos, yPos; + double mTimeUntilNextFrame, msPerFrame = 1000/60; public: TomatoObject(int x, int y) { xPos = x; yPos = y; }; int getX() { return xPos; }; int getY() { return yPos; }; - void Update() { xPos--; }; + void Update(double deltaTime) + { + mTimeUntilNextFrame -= deltaTime; + if (mTimeUntilNextFrame <= 0) + { + mTimeUntilNextFrame = msPerFrame; + xPos--; + } + }; +}; + +/* Timer - high accuracy timer - uses Large Integer to prevent rollover +Dean Lawson +Champlain College +2011 +*/ + +class Timer +{ + +private: + LARGE_INTEGER mStartTime; + LARGE_INTEGER mEndTime; + LARGE_INTEGER mTimerFrequency; + double mElapsedTime; + double mFactor; + double mLastFactor; + bool mPaused; + + //helper function - uses current frequency for the Timer + double calcDifferenceInMS(LARGE_INTEGER from, LARGE_INTEGER to) const + { + double difference = (double)(to.QuadPart - from.QuadPart) / (double)mTimerFrequency.QuadPart; + difference *= mFactor; + return difference * 1000; + } +public: + Timer() + :mElapsedTime(0.0) + , mPaused(true) + , mFactor(1.0) + , mLastFactor(1.0) + { + QueryPerformanceFrequency(&mTimerFrequency); + mStartTime.QuadPart = 0; + mEndTime.QuadPart = 0; + } + ~Timer() + { + } + + void start() + { + QueryPerformanceCounter(&mStartTime); + + //reset end time as well + mEndTime.QuadPart = 0; + + mElapsedTime = 0.0; + + pause(false);//unpause + } + void stop() + { + QueryPerformanceCounter(&mEndTime); + mElapsedTime = calcDifferenceInMS(mStartTime, mEndTime); + } + double getElapsedTime() const//returns how much time has elapsed since start + { + //if we have an end time then the timer isn't running and we can just return the elapsed time + if (mEndTime.QuadPart != 0) + { + return mElapsedTime; + } + else //otherwise we need to get the current time, do the math and return that + { + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + return calcDifferenceInMS(mStartTime, currentTime); + } + } + void sleepUntilElapsed(double ms) + { + LARGE_INTEGER currentTime, lastTime; + QueryPerformanceCounter(¤tTime); + double timeToSleep = ms - calcDifferenceInMS(mStartTime, currentTime); + + while (timeToSleep > 0.0) + { + lastTime = currentTime; + QueryPerformanceCounter(¤tTime); + double timeElapsed = calcDifferenceInMS(lastTime, currentTime); + timeToSleep -= timeElapsed; + if (timeToSleep > 10.0)//if we are going to be in this loop for a long time - + { //Sleep to relinquish back to Windows + Sleep(10); + } + } + } + void pause(bool shouldPause) + { + if (shouldPause && !mPaused)//want to pause and we are not currently paused + { + mPaused = true; + QueryPerformanceCounter(&mEndTime); + mElapsedTime += calcDifferenceInMS(mStartTime, mEndTime); + } + else if (!shouldPause && mPaused)//want to unpause and we are paused + { + mPaused = false; + QueryPerformanceCounter(&mStartTime); + } + } + inline double getFactor() const { return mFactor; }; + inline void multFactor(double mult) { mLastFactor = mFactor; mFactor *= mult; }; + inline void setFactor(double theFactor) { mLastFactor = mFactor; mFactor = theFactor; }; + inline void restoreLastFactor() { mFactor = mLastFactor; }; + }; class GameState @@ -134,6 +252,7 @@ class GameState PlayerGameObject* otherPlayer; vector vCoins; TomatoObject* tomato; + double mTimePerFrame; public: GameState(bool serverState, string ourAddr, string other) { @@ -165,8 +284,9 @@ class GameState { delete mLibrary; } - void Update() + void Update()//make time a part of this so that it runs the same rate on all systems { + Timer timer; mLibrary->loadImage("../2517597.jpg", "background"); mLibrary->loadImage("../coin.png", "coin"); mLibrary->loadImage("../tomato.png", "tomato"); @@ -189,9 +309,10 @@ class GameState while (!escapePressed) { + timer.start(); if (isServer) { - tomato->Update(); + tomato->Update(mTimePerFrame); SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::TOMATO, tomato->getX(), tomato->getY()); CheckForCollisions(mPlayer); CheckForCollisions(otherPlayer); @@ -216,6 +337,7 @@ class GameState mLibrary->render(); mLibrary->drawImage("background", 0, 0); + timer.sleepUntilElapsed(mTimePerFrame); } } void SendPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, @@ -228,11 +350,13 @@ class GameState packet[3] = pos_y; char* bytePacket = (char*)packet; - - int bytesSent = ptr->SendTo(bytePacket, 100, *addr); - if (bytesSent <= 0) + if (rand() % 16 != 5) { - SocketUtil::ReportError("Client SendTo"); + int bytesSent = ptr->SendTo(bytePacket, 100, *addr); + if (bytesSent <= 0) + { + SocketUtil::ReportError("Client SendTo"); + } } } void SendCoinPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, vector coins) @@ -247,14 +371,16 @@ class GameState } char* bytePacket = (char*)packet; - - int bytesSent = ptr->SendTo(bytePacket, 100, *addr); - if (bytesSent <= 0) + if (rand() % 16 != 5) { - SocketUtil::ReportError("Client SendTo"); + int bytesSent = ptr->SendTo(bytePacket, 100, *addr); + if (bytesSent <= 0) + { + SocketUtil::ReportError("Client SendTo"); + } } } - void ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr, InputSystem* mInputSystem) + int* ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr, InputSystem* mInputSystem) { char buffer[100]; { @@ -358,7 +484,6 @@ int main(int argc, const char** argv) srand(time(NULL)); SocketUtil::StaticInit(); - //DoThreadExample(); GameState* state; bool isServer = StringUtils::GetCommandLineArg(1) == "server"; @@ -374,8 +499,6 @@ int main(int argc, const char** argv) state->Update(); - //cin.get(); - SocketUtil::CleanUp(); delete state; From 5a8eac2fb02c4f9bbab5eda4298858092b892509 Mon Sep 17 00:00:00 2001 From: Hopp Date: Tue, 5 Apr 2022 14:09:56 -0400 Subject: [PATCH 3/7] made packet struct for priority queue --- RoboCat/Src/Main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 9bd29248..75d013d3 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -40,6 +40,17 @@ UDPSocketPtr CreateBoundSocket(std::string IP) return cliSock; } +struct Packet +{ + int* buffer; + time_t timeStamp; + + friend bool operator<(const Packet& a, const Packet& b) + { + return a.timeStamp > b.timeStamp; + }; +}; + class PlayerGameObject { private: @@ -284,6 +295,7 @@ class GameState { delete mLibrary; } + //change receive method to return the packet, put the packet in a priority (?) queue of returned packets along with a time stamp, only process packets received x seconds ago void Update()//make time a part of this so that it runs the same rate on all systems { Timer timer; From a6362a6280c375f09059863b256fd17cc25214f9 Mon Sep 17 00:00:00 2001 From: Tempest Hopp Date: Tue, 5 Apr 2022 18:19:33 -0400 Subject: [PATCH 4/7] made primitive code to sim jitter and latency --- RoboCat/Src/Main.cpp | 74 ++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 75d013d3..32f9188d 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -40,15 +40,26 @@ UDPSocketPtr CreateBoundSocket(std::string IP) return cliSock; } -struct Packet +class Packet { - int* buffer; - time_t timeStamp; + private: + int* buffer; + long int timeStamp; - friend bool operator<(const Packet& a, const Packet& b) - { - return a.timeStamp > b.timeStamp; - }; + public: + Packet(int* b, long int time) + { + buffer = b; + timeStamp = time; + } + + long int getTimeStamp() { return timeStamp; }; + int* getBuffer() { return buffer; }; + + friend bool operator<(const Packet& a, const Packet& b) + { + return a.timeStamp > b.timeStamp; + }; }; class PlayerGameObject @@ -263,7 +274,9 @@ class GameState PlayerGameObject* otherPlayer; vector vCoins; TomatoObject* tomato; - double mTimePerFrame; + double mTimePerFrame = 1000/60; + long int timeBeforeProcessing = 5; + priority_queue mReceivedPackets; public: GameState(bool serverState, string ourAddr, string other) { @@ -331,14 +344,24 @@ class GameState } else { - ReceivePacket(sock, &otherAddr, mInputSystem); + mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr, mInputSystem), static_cast(time(NULL)) + rand() % 6 - 3)); } SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::PLAYER, mPlayer->getX(), mPlayer->getY()); - ReceivePacket(sock, &otherAddr, mInputSystem); + mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr, mInputSystem), static_cast(time(NULL)) + rand() % 6 - 3)); + + while (static_cast (time(NULL)) - mReceivedPackets.top()->getTimeStamp() < timeBeforeProcessing) + { + Packet* temp = mReceivedPackets.top(); + mReceivedPackets.pop(); + processPacket(temp->getBuffer()); + delete temp; + } + for (auto& coin : vCoins) { mLibrary->drawImage("coin", coin->getX(), coin->getY()); } + mLibrary->drawImage("tomato", tomato->getX(), tomato->getY()); int keyPress = mInputSystem->getKeyboardInput(); mPlayer->Update(keyPress); @@ -406,12 +429,19 @@ class GameState else { int* packet = (int*)buffer; - switch (packet[0]) - { - case PacketTypes::UPDATE: + return packet; + } + } + } + + void processPacket(int* packet) + { + switch (packet[0]) + { + case PacketTypes::UPDATE: + { + switch (packet[1]) { - switch (packet[1]) - { case ObjectTypes::PLAYER: { otherPlayer->setX(packet[2]); @@ -432,15 +462,13 @@ class GameState tomato = new TomatoObject(packet[2], packet[3]); break; } - } - break; - } - case PacketTypes::HELLO: - { - SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); - break; - } } + break; + } + case PacketTypes::HELLO: + { + SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); + break; } } } From 9501a93f308fe88b6382b13b5033cfeaf9a63ca9 Mon Sep 17 00:00:00 2001 From: Tempest Hopp Date: Thu, 7 Apr 2022 15:03:52 -0400 Subject: [PATCH 5/7] cleared up errors so I can start testing --- RoboCat/Src/Main.cpp | 46 ++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 32f9188d..21bc4999 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -349,7 +349,7 @@ class GameState SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::PLAYER, mPlayer->getX(), mPlayer->getY()); mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr, mInputSystem), static_cast(time(NULL)) + rand() % 6 - 3)); - while (static_cast (time(NULL)) - mReceivedPackets.top()->getTimeStamp() < timeBeforeProcessing) + while (!mReceivedPackets.empty() && static_cast (time(NULL)) - mReceivedPackets.top()->getTimeStamp() < timeBeforeProcessing) { Packet* temp = mReceivedPackets.top(); mReceivedPackets.pop(); @@ -425,43 +425,46 @@ class GameState SocketUtil::ReportError("Error receiving packet"); } else if (bytesReceived == 0) - return; + return nullptr; else { int* packet = (int*)buffer; return packet; } } + return nullptr; } void processPacket(int* packet) { - switch (packet[0]) + if (packet != nullptr) { + switch (packet[0]) + { case PacketTypes::UPDATE: { switch (packet[1]) { - case ObjectTypes::PLAYER: - { - otherPlayer->setX(packet[2]); - otherPlayer->setY(packet[3]); - break; - } - case ObjectTypes::COIN: - { - vCoins.clear(); - for (int i = 2; i < 20; i += 2) - { - vCoins.push_back(new CoinObject(packet[i], packet[i + 1])); - } - break; - } - case ObjectTypes::TOMATO: + case ObjectTypes::PLAYER: + { + otherPlayer->setX(packet[2]); + otherPlayer->setY(packet[3]); + break; + } + case ObjectTypes::COIN: + { + vCoins.clear(); + for (int i = 2; i < 20; i += 2) { - tomato = new TomatoObject(packet[2], packet[3]); - break; + vCoins.push_back(new CoinObject(packet[i], packet[i + 1])); } + break; + } + case ObjectTypes::TOMATO: + { + tomato = new TomatoObject(packet[2], packet[3]); + break; + } } break; } @@ -470,6 +473,7 @@ class GameState SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); break; } + } } } From 2e934ffb00f89c036639878a9a3e6f125570b108 Mon Sep 17 00:00:00 2001 From: Tempest Hopp Date: Fri, 8 Apr 2022 12:54:06 -0400 Subject: [PATCH 6/7] don't remember what I changed --- RoboCat/Src/Main.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 21bc4999..1cf44fde 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -344,16 +344,26 @@ class GameState } else { - mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr, mInputSystem), static_cast(time(NULL)) + rand() % 6 - 3)); + mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr), static_cast(time(NULL)) + rand() % 6 - 3)); } SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::PLAYER, mPlayer->getX(), mPlayer->getY()); - mReceivedPackets.push(new Packet(ReceivePacket(sock, &otherAddr, mInputSystem), static_cast(time(NULL)) + rand() % 6 - 3)); + int* temp = ReceivePacket(sock, &otherAddr); + if (temp != nullptr) + cout << temp[0] << endl; + mReceivedPackets.push(new Packet(temp, static_cast(time(NULL)) + rand() % 6 - 3)); + //cout << mReceivedPackets.empty() << endl; while (!mReceivedPackets.empty() && static_cast (time(NULL)) - mReceivedPackets.top()->getTimeStamp() < timeBeforeProcessing) { + cout << mReceivedPackets.top()->getBuffer()[0] << endl; Packet* temp = mReceivedPackets.top(); mReceivedPackets.pop(); - processPacket(temp->getBuffer()); + if (temp != nullptr) + { + //cout << mReceivedPackets.top()->getBuffer()[0] << endl; + //cout << temp->getBuffer()[0] << endl; + processPacket(temp->getBuffer()); + } delete temp; } @@ -387,11 +397,13 @@ class GameState char* bytePacket = (char*)packet; if (rand() % 16 != 5) { + //cout << rand() % 16 << endl; int bytesSent = ptr->SendTo(bytePacket, 100, *addr); if (bytesSent <= 0) { SocketUtil::ReportError("Client SendTo"); } + //cout << "sent packet" << endl; } } void SendCoinPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, vector coins) @@ -413,9 +425,10 @@ class GameState { SocketUtil::ReportError("Client SendTo"); } + //cout << "sent coin packet" << endl; } } - int* ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr, InputSystem* mInputSystem) + int* ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr) { char buffer[100]; { @@ -428,7 +441,9 @@ class GameState return nullptr; else { + //cout << "received packet" << endl; int* packet = (int*)buffer; + //cout << packet[0] << endl; return packet; } } @@ -439,6 +454,7 @@ class GameState { if (packet != nullptr) { + cout << packet[0] << endl; switch (packet[0]) { case PacketTypes::UPDATE: From f8c25b6fbd515d827ed0da666dc2869a029dbf69 Mon Sep 17 00:00:00 2001 From: Hopp Date: Fri, 8 Apr 2022 14:12:46 -0400 Subject: [PATCH 7/7] assignment done (in theory) --- RoboCat/Chapter3.vcxproj | 3 +- RoboCat/Src/Main.cpp | 42 +- RoboCat/log.txt | 5905 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 5927 insertions(+), 23 deletions(-) create mode 100644 RoboCat/log.txt diff --git a/RoboCat/Chapter3.vcxproj b/RoboCat/Chapter3.vcxproj index 5b18b0b9..753e15c6 100644 --- a/RoboCat/Chapter3.vcxproj +++ b/RoboCat/Chapter3.vcxproj @@ -31,12 +31,13 @@ {B3B75176-8D81-4E7B-A5D0-C2E5423844D3} SimpleSample Win32Proj + 10.0 Application MultiByte - v142 + v143 Application diff --git a/RoboCat/Src/Main.cpp b/RoboCat/Src/Main.cpp index 1cf44fde..3078e25c 100644 --- a/RoboCat/Src/Main.cpp +++ b/RoboCat/Src/Main.cpp @@ -339,6 +339,7 @@ class GameState { tomato->Update(mTimePerFrame); SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::TOMATO, tomato->getX(), tomato->getY()); + SendCoinPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::COIN, vCoins); CheckForCollisions(mPlayer); CheckForCollisions(otherPlayer); } @@ -348,23 +349,17 @@ class GameState } SendPacket(sock, &otherAddr, PacketTypes::UPDATE, ObjectTypes::PLAYER, mPlayer->getX(), mPlayer->getY()); int* temp = ReceivePacket(sock, &otherAddr); - if (temp != nullptr) - cout << temp[0] << endl; mReceivedPackets.push(new Packet(temp, static_cast(time(NULL)) + rand() % 6 - 3)); - //cout << mReceivedPackets.empty() << endl; while (!mReceivedPackets.empty() && static_cast (time(NULL)) - mReceivedPackets.top()->getTimeStamp() < timeBeforeProcessing) { - cout << mReceivedPackets.top()->getBuffer()[0] << endl; - Packet* temp = mReceivedPackets.top(); + Packet* tempPacket = mReceivedPackets.top(); mReceivedPackets.pop(); - if (temp != nullptr) + if (tempPacket != nullptr) { - //cout << mReceivedPackets.top()->getBuffer()[0] << endl; - //cout << temp->getBuffer()[0] << endl; - processPacket(temp->getBuffer()); + processPacket(tempPacket->getBuffer()); } - delete temp; + delete tempPacket; } for (auto& coin : vCoins) @@ -388,22 +383,20 @@ class GameState void SendPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, int pos_x, int pos_y) { - int packet[25]; + const int packetSize = sizeof(int) * 25; + int packet[packetSize / sizeof(int)]; packet[0] = packetType; packet[1] = objectType; packet[2] = pos_x; packet[3] = pos_y; - char* bytePacket = (char*)packet; if (rand() % 16 != 5) { - //cout << rand() % 16 << endl; - int bytesSent = ptr->SendTo(bytePacket, 100, *addr); + int bytesSent = ptr->SendTo((char*)packet, packetSize, *addr); if (bytesSent <= 0) { SocketUtil::ReportError("Client SendTo"); } - //cout << "sent packet" << endl; } } void SendCoinPacket(UDPSocketPtr ptr, SocketAddress* addr, int packetType, int objectType, vector coins) @@ -411,7 +404,7 @@ class GameState int packet[25]; packet[0] = packetType; packet[1] = objectType; - for (int i = 2; i < 20; i += 2) + for (int i = 2; i < 22; i += 2) { packet[i] = coins[i / 2 - 1]->getX(); packet[i + 1] = coins[i / 2 - 1]->getY(); @@ -425,7 +418,6 @@ class GameState { SocketUtil::ReportError("Client SendTo"); } - //cout << "sent coin packet" << endl; } } int* ReceivePacket(UDPSocketPtr ptr, SocketAddress* addr) @@ -441,10 +433,14 @@ class GameState return nullptr; else { - //cout << "received packet" << endl; - int* packet = (int*)buffer; - //cout << packet[0] << endl; - return packet; + char* packet = new char[100]; + for (int i = 0; i < 100; i++) + { + packet[i] = buffer[i]; + } + int* pac = (int*)packet; + cout << pac[2] << ", " << pac[3] << endl; + return pac; } } return nullptr; @@ -469,11 +465,13 @@ class GameState } case ObjectTypes::COIN: { + cout << "coin packet received" << endl; vCoins.clear(); - for (int i = 2; i < 20; i += 2) + for (int i = 2; i < 22; i += 2) { vCoins.push_back(new CoinObject(packet[i], packet[i + 1])); } + cout << vCoins.size() << endl; break; } case ObjectTypes::TOMATO: diff --git a/RoboCat/log.txt b/RoboCat/log.txt new file mode 100644 index 00000000..4eca3960 --- /dev/null +++ b/RoboCat/log.txt @@ -0,0 +1,5905 @@ +127.0.0.1:9000 +701, 307 +650, 100 +1 +1 +700, 307 +650, 100 +1 +1 +699, 307 +650, 100 +1 +1 +698, 307 +650, 100 +1 +1 +697, 307 +650, 100 +1 +1 +696, 307 +650, 100 +1 +1 +695, 307 +694, 307 +1 +1 +650, 100 +693, 307 +1 +1 +692, 307 +650, 100 +1 +1 +691, 307 +690, 307 +1 +1 +650, 100 +689, 307 +1 +1 +650, 100 +688, 307 +1 +1 +650, 100 +687, 307 +1 +1 +650, 100 +686, 307 +1 +1 +650, 100 +685, 307 +1 +1 +650, 100 +684, 307 +1 +1 +650, 100 +683, 307 +1 +1 +650, 100 +682, 307 +1 +1 +650, 100 +650, 100 +1 +1 +680, 307 +650, 100 +1 +1 +679, 307 +650, 100 +1 +1 +678, 307 +650, 100 +1 +1 +677, 307 +650, 100 +1 +1 +650, 100 +675, 307 +1 +1 +650, 100 +674, 307 +1 +1 +673, 307 +650, 100 +1 +1 +672, 307 +650, 100 +1 +1 +671, 307 +650, 100 +1 +1 +670, 307 +650, 100 +1 +1 +669, 307 +650, 100 +1 +1 +668, 307 +667, 307 +1 +1 +650, 100 +666, 307 +1 +1 +650, 100 +665, 307 +1 +1 +650, 100 +664, 307 +1 +1 +650, 100 +663, 307 +1 +1 +650, 100 +662, 307 +1 +1 +650, 100 +661, 307 +1 +1 +650, 100 +660, 307 +1 +1 +650, 100 +659, 307 +1 +1 +650, 100 +658, 307 +1 +1 +650, 100 +657, 307 +1 +1 +650, 100 +656, 307 +1 +1 +650, 100 +655, 307 +1 +1 +650, 100 +654, 307 +1 +1 +650, 100 +653, 307 +1 +1 +650, 100 +652, 307 +1 +1 +650, 100 +651, 307 +1 +1 +650, 100 +650, 307 +1 +1 +650, 100 +649, 307 +1 +1 +650, 100 +648, 307 +1 +1 +650, 100 +647, 307 +1 +1 +650, 100 +646, 307 +1 +1 +650, 100 +645, 307 +1 +1 +650, 100 +644, 307 +1 +1 +650, 100 +643, 307 +1 +1 +650, 100 +642, 307 +1 +1 +650, 100 +641, 307 +1 +1 +650, 100 +640, 307 +1 +1 +650, 100 +639, 307 +1 +1 +650, 100 +638, 307 +1 +1 +650, 100 +637, 307 +1 +1 +650, 100 +636, 307 +1 +1 +635, 307 +650, 100 +1 +1 +634, 307 +650, 100 +1 +1 +633, 307 +650, 100 +1 +1 +632, 307 +650, 100 +1 +1 +631, 307 +650, 100 +1 +1 +630, 307 +650, 100 +1 +1 +629, 307 +650, 100 +1 +1 +628, 307 +650, 100 +1 +1 +627, 307 +650, 100 +1 +1 +626, 307 +650, 100 +1 +1 +625, 307 +650, 100 +1 +1 +624, 307 +650, 100 +1 +1 +623, 307 +650, 100 +1 +1 +622, 307 +650, 100 +1 +1 +621, 307 +650, 100 +1 +1 +620, 307 +650, 100 +1 +1 +619, 307 +650, 100 +1 +1 +650, 100 +617, 307 +1 +1 +650, 100 +616, 307 +1 +1 +650, 100 +615, 307 +1 +1 +650, 100 +614, 307 +1 +1 +650, 100 +613, 307 +1 +1 +650, 100 +612, 307 +1 +1 +650, 100 +611, 307 +1 +1 +610, 307 +650, 100 +1 +1 +609, 307 +650, 100 +1 +1 +608, 307 +650, 100 +1 +1 +607, 307 +650, 100 +1 +1 +606, 307 +650, 100 +1 +1 +605, 307 +650, 100 +1 +1 +604, 307 +650, 100 +1 +1 +603, 307 +650, 100 +1 +1 +602, 307 +650, 100 +1 +1 +601, 307 +650, 100 +1 +1 +600, 307 +650, 100 +1 +1 +599, 307 +650, 100 +1 +1 +598, 307 +650, 100 +1 +1 +597, 307 +650, 100 +1 +1 +596, 307 +650, 100 +1 +1 +595, 307 +650, 100 +1 +1 +594, 307 +650, 100 +1 +1 +593, 307 +650, 100 +1 +1 +592, 307 +650, 100 +1 +1 +591, 307 +590, 307 +1 +1 +650, 100 +589, 307 +1 +1 +650, 100 +588, 307 +1 +1 +650, 100 +587, 307 +1 +1 +650, 100 +586, 307 +1 +1 +650, 100 +585, 307 +1 +1 +650, 100 +584, 307 +1 +1 +650, 100 +583, 307 +1 +1 +650, 100 +582, 307 +1 +1 +650, 100 +581, 307 +1 +1 +650, 100 +580, 307 +1 +1 +650, 100 +579, 307 +1 +1 +650, 100 +578, 307 +1 +1 +650, 100 +577, 307 +1 +1 +650, 100 +576, 307 +1 +1 +650, 100 +575, 307 +1 +1 +650, 100 +574, 307 +1 +1 +650, 100 +650, 100 +1 +1 +572, 307 +650, 100 +1 +1 +571, 307 +650, 100 +1 +1 +570, 307 +569, 307 +1 +1 +650, 100 +568, 307 +1 +1 +650, 100 +567, 307 +1 +1 +650, 100 +566, 307 +1 +1 +650, 100 +565, 307 +1 +1 +650, 100 +650, 100 +1 +1 +563, 307 +650, 100 +1 +1 +562, 307 +650, 100 +1 +1 +561, 307 +650, 100 +1 +1 +560, 307 +650, 100 +1 +1 +559, 307 +650, 100 +1 +1 +558, 307 +650, 100 +1 +1 +557, 307 +650, 100 +1 +1 +556, 307 +650, 100 +1 +1 +555, 307 +650, 100 +1 +1 +554, 307 +650, 100 +1 +1 +553, 307 +650, 100 +1 +1 +552, 307 +650, 100 +1 +1 +551, 307 +650, 100 +1 +1 +550, 307 +549, 307 +1 +1 +650, 100 +650, 100 +1 +1 +547, 307 +650, 100 +1 +1 +546, 307 +650, 100 +1 +1 +545, 307 +650, 100 +1 +1 +650, 100 +543, 307 +1 +1 +650, 100 +542, 307 +1 +1 +650, 100 +541, 307 +1 +1 +650, 100 +650, 100 +1 +1 +539, 307 +650, 100 +1 +1 +538, 307 +650, 100 +1 +1 +537, 307 +650, 100 +1 +1 +536, 307 +650, 100 +1 +1 +535, 307 +650, 100 +1 +1 +650, 100 +533, 307 +1 +1 +650, 100 +532, 307 +1 +1 +650, 100 +531, 307 +1 +1 +650, 100 +530, 307 +1 +1 +650, 100 +529, 307 +1 +1 +650, 100 +528, 307 +1 +1 +650, 100 +527, 307 +1 +1 +650, 100 +526, 307 +1 +1 +650, 100 +525, 307 +1 +1 +650, 100 +524, 307 +1 +1 +650, 100 +523, 307 +1 +1 +650, 100 +522, 307 +1 +1 +650, 100 +521, 307 +1 +1 +650, 100 +520, 307 +1 +1 +650, 100 +519, 307 +1 +1 +650, 100 +518, 307 +1 +1 +650, 100 +517, 307 +1 +1 +650, 100 +516, 307 +1 +1 +650, 100 +515, 307 +1 +1 +650, 100 +514, 307 +1 +1 +650, 100 +513, 307 +1 +1 +650, 100 +512, 307 +1 +1 +650, 100 +511, 307 +1 +1 +650, 100 +510, 307 +1 +1 +650, 100 +509, 307 +1 +1 +650, 100 +508, 307 +1 +1 +650, 100 +507, 307 +1 +1 +650, 100 +506, 307 +1 +1 +650, 100 +505, 307 +1 +1 +650, 100 +504, 307 +1 +1 +650, 100 +503, 307 +1 +1 +650, 100 +502, 307 +1 +1 +650, 100 +501, 307 +1 +1 +650, 100 +500, 307 +1 +1 +650, 100 +499, 307 +1 +1 +650, 100 +498, 307 +1 +1 +650, 100 +497, 307 +1 +1 +650, 100 +496, 307 +1 +1 +650, 100 +495, 307 +1 +1 +494, 307 +650, 100 +1 +1 +493, 307 +650, 100 +1 +1 +492, 307 +650, 100 +1 +1 +491, 307 +650, 100 +1 +1 +490, 307 +650, 100 +1 +1 +489, 307 +650, 100 +1 +1 +488, 307 +650, 100 +1 +1 +487, 307 +650, 100 +1 +1 +486, 307 +650, 100 +1 +1 +485, 307 +650, 100 +1 +1 +484, 307 +650, 100 +1 +1 +650, 100 +482, 307 +1 +1 +650, 100 +480, 307 +1 +1 +650, 100 +479, 307 +1 +1 +650, 100 +478, 307 +1 +1 +650, 100 +477, 307 +1 +1 +650, 100 +476, 307 +1 +1 +650, 100 +650, 100 +1 +1 +474, 307 +650, 100 +1 +1 +473, 307 +650, 100 +1 +1 +471, 307 +650, 100 +1 +1 +470, 307 +650, 100 +1 +1 +469, 307 +650, 100 +1 +1 +468, 307 +650, 100 +1 +1 +467, 307 +650, 100 +1 +1 +466, 307 +650, 100 +1 +1 +465, 307 +650, 100 +1 +1 +464, 307 +650, 100 +1 +1 +463, 307 +650, 100 +1 +1 +462, 307 +650, 100 +1 +1 +461, 307 +650, 100 +1 +1 +460, 307 +1 +459, 307 +650, 100 +1 +1 +458, 307 +650, 100 +1 +1 +457, 307 +650, 100 +1 +1 +456, 307 +650, 100 +1 +1 +455, 307 +650, 100 +1 +1 +454, 307 +650, 100 +1 +1 +453, 307 +650, 100 +1 +1 +452, 307 +650, 100 +1 +1 +451, 307 +650, 100 +1 +1 +450, 307 +650, 100 +1 +1 +449, 307 +650, 100 +1 +1 +650, 100 +1 +447, 307 +650, 100 +1 +1 +446, 307 +650, 100 +1 +1 +445, 307 +650, 100 +1 +1 +650, 100 +1 +443, 307 +650, 100 +1 +1 +442, 307 +650, 100 +1 +1 +441, 307 +650, 100 +1 +1 +440, 307 +650, 100 +1 +1 +439, 307 +650, 100 +1 +1 +438, 307 +650, 100 +1 +1 +437, 307 +650, 100 +1 +1 +650, 100 +1 +435, 307 +650, 100 +1 +1 +434, 307 +1 +433, 307 +650, 100 +1 +1 +432, 307 +650, 100 +1 +1 +431, 307 +650, 100 +1 +1 +650, 100 +1 +429, 307 +650, 100 +1 +1 +428, 307 +650, 100 +1 +1 +427, 307 +650, 100 +1 +1 +426, 307 +650, 100 +1 +1 +425, 307 +1 +424, 307 +650, 100 +1 +1 +423, 307 +650, 100 +1 +1 +422, 307 +650, 100 +1 +1 +421, 307 +650, 100 +1 +1 +420, 307 +1 +419, 307 +650, 100 +1 +1 +418, 307 +650, 100 +1 +1 +417, 307 +650, 100 +1 +1 +416, 307 +650, 100 +1 +1 +415, 307 +650, 100 +1 +1 +414, 307 +650, 100 +1 +1 +413, 307 +650, 100 +1 +1 +412, 307 +650, 100 +1 +1 +411, 307 +650, 100 +1 +1 +410, 307 +650, 100 +1 +1 +409, 307 +1 +408, 307 +1 +407, 307 +650, 100 +1 +1 +406, 307 +650, 100 +1 +1 +405, 307 +650, 100 +1 +1 +404, 307 +650, 100 +1 +1 +403, 307 +650, 100 +1 +1 +402, 307 +650, 100 +1 +1 +401, 307 +650, 100 +1 +1 +400, 307 +650, 100 +1 +1 +399, 307 +650, 100 +1 +1 +398, 307 +650, 100 +1 +1 +397, 307 +650, 100 +1 +1 +396, 307 +650, 100 +1 +1 +395, 307 +650, 100 +1 +1 +394, 307 +650, 100 +1 +1 +393, 307 +650, 100 +1 +1 +392, 307 +650, 100 +1 +1 +391, 307 +650, 100 +1 +1 +390, 307 +650, 100 +1 +1 +389, 307 +650, 100 +1 +1 +388, 307 +650, 100 +1 +1 +387, 307 +650, 100 +1 +1 +386, 307 +650, 100 +1 +1 +385, 307 +650, 100 +1 +1 +384, 307 +650, 100 +1 +1 +383, 307 +650, 100 +1 +1 +650, 100 +1 +381, 307 +650, 100 +1 +1 +380, 307 +1 +379, 307 +650, 100 +1 +1 +378, 307 +650, 100 +1 +1 +377, 307 +650, 100 +1 +1 +376, 307 +650, 100 +1 +1 +375, 307 +650, 100 +1 +1 +374, 307 +650, 100 +1 +1 +373, 307 +650, 100 +1 +1 +372, 307 +650, 100 +1 +1 +371, 307 +650, 100 +1 +1 +370, 307 +1 +369, 307 +1 +368, 307 +650, 100 +1 +1 +367, 307 +650, 100 +1 +1 +366, 307 +650, 100 +1 +1 +365, 307 +650, 100 +1 +1 +364, 307 +650, 100 +1 +1 +363, 307 +1 +362, 307 +1 +361, 307 +650, 100 +1 +1 +359, 307 +650, 100 +1 +1 +358, 307 +650, 100 +1 +1 +357, 307 +650, 100 +1 +1 +356, 307 +1 +355, 307 +650, 100 +1 +1 +354, 307 +650, 100 +1 +1 +353, 307 +650, 100 +1 +1 +352, 307 +1 +351, 307 +650, 100 +1 +1 +350, 307 +650, 100 +1 +1 +349, 307 +650, 100 +1 +1 +650, 100 +1 +347, 307 +650, 100 +1 +1 +346, 307 +650, 100 +1 +1 +345, 307 +650, 100 +1 +1 +344, 307 +650, 100 +1 +1 +343, 307 +650, 100 +1 +1 +342, 307 +1 +341, 307 +650, 100 +1 +1 +340, 307 +650, 100 +1 +1 +339, 307 +650, 100 +1 +1 +338, 307 +650, 100 +1 +1 +337, 307 +650, 100 +1 +1 +336, 307 +650, 100 +1 +1 +335, 307 +650, 100 +1 +1 +334, 307 +650, 100 +1 +1 +333, 307 +650, 100 +1 +1 +332, 307 +650, 100 +1 +1 +331, 307 +650, 100 +1 +1 +650, 100 +1 +329, 307 +650, 100 +1 +1 +328, 307 +650, 100 +1 +1 +327, 307 +650, 100 +1 +1 +326, 307 +650, 100 +1 +1 +650, 100 +1 +324, 307 +650, 100 +1 +1 +323, 307 +1 +322, 307 +650, 100 +1 +1 +321, 307 +650, 100 +1 +1 +320, 307 +650, 100 +1 +1 +319, 307 +650, 100 +1 +1 +318, 307 +1 +650, 100 +1 +316, 307 +1 +315, 307 +650, 100 +1 +1 +314, 307 +650, 100 +1 +1 +650, 100 +1 +312, 307 +650, 100 +1 +1 +311, 307 +650, 100 +1 +1 +650, 100 +1 +309, 307 +650, 100 +1 +1 +308, 307 +650, 100 +1 +1 +307, 307 +650, 100 +1 +1 +306, 307 +650, 100 +1 +1 +305, 307 +650, 100 +1 +1 +304, 307 +1 +303, 307 +650, 100 +1 +1 +302, 307 +650, 100 +1 +1 +301, 307 +650, 100 +1 +1 +300, 307 +650, 100 +1 +1 +299, 307 +650, 100 +1 +1 +298, 307 +650, 100 +1 +1 +297, 307 +650, 100 +1 +1 +296, 307 +650, 100 +1 +1 +295, 307 +650, 100 +1 +1 +294, 307 +650, 100 +1 +1 +293, 307 +650, 100 +1 +1 +292, 307 +650, 100 +1 +1 +291, 307 +650, 100 +1 +1 +290, 307 +650, 100 +1 +1 +289, 307 +650, 100 +1 +1 +288, 307 +650, 100 +1 +1 +287, 307 +650, 100 +1 +1 +650, 100 +1 +285, 307 +650, 100 +1 +1 +284, 307 +650, 100 +1 +1 +283, 307 +650, 100 +1 +1 +282, 307 +650, 100 +1 +1 +281, 307 +650, 100 +1 +1 +280, 307 +1 +279, 307 +650, 100 +1 +1 +278, 307 +650, 100 +1 +1 +277, 307 +650, 100 +1 +1 +276, 307 +650, 100 +1 +1 +650, 100 +1 +274, 307 +650, 100 +1 +1 +273, 307 +650, 100 +1 +1 +272, 307 +650, 100 +1 +1 +271, 307 +650, 100 +1 +1 +270, 307 +1 +269, 307 +650, 100 +1 +1 +268, 307 +650, 100 +1 +1 +267, 307 +650, 100 +1 +1 +266, 307 +1 +265, 307 +650, 100 +1 +1 +264, 307 +650, 100 +1 +1 +263, 307 +650, 100 +1 +1 +262, 307 +650, 100 +1 +1 +650, 100 +1 +260, 307 +650, 100 +1 +1 +259, 307 +650, 100 +1 +1 +258, 307 +650, 100 +1 +1 +257, 307 +650, 100 +1 +1 +256, 307 +650, 100 +1 +1 +255, 307 +650, 100 +1 +1 +254, 307 +650, 100 +1 +1 +253, 307 +650, 100 +1 +1 +252, 307 +650, 100 +1 +1 +251, 307 +650, 100 +1 +1 +250, 307 +650, 100 +1 +1 +650, 100 +1 +248, 307 +650, 100 +1 +1 +247, 307 +650, 100 +1 +1 +246, 307 +650, 100 +1 +1 +245, 307 +650, 100 +1 +1 +244, 307 +650, 100 +1 +1 +243, 307 +650, 100 +1 +1 +650, 100 +1 +241, 307 +650, 100 +1 +1 +240, 307 +1 +239, 307 +650, 100 +1 +1 +238, 307 +650, 100 +1 +1 +237, 307 +650, 100 +1 +1 +236, 307 +650, 100 +1 +1 +235, 307 +650, 100 +1 +1 +234, 307 +650, 100 +1 +1 +233, 307 +650, 100 +1 +1 +232, 307 +650, 100 +1 +1 +231, 307 +650, 100 +1 +1 +230, 307 +650, 100 +1 +1 +229, 307 +650, 100 +1 +1 +228, 307 +650, 100 +1 +1 +227, 307 +650, 100 +1 +1 +226, 307 +650, 100 +1 +1 +225, 307 +650, 100 +1 +1 +224, 307 +650, 100 +1 +1 +223, 307 +650, 100 +1 +1 +222, 307 +650, 100 +1 +1 +221, 307 +650, 100 +1 +1 +220, 307 +650, 100 +1 +1 +219, 307 +1 +218, 307 +650, 100 +1 +1 +217, 307 +650, 100 +1 +1 +216, 307 +650, 100 +1 +1 +215, 307 +650, 100 +1 +1 +214, 307 +650, 100 +1 +1 +213, 307 +650, 100 +1 +1 +212, 307 +650, 100 +1 +1 +211, 307 +650, 100 +1 +1 +210, 307 +650, 100 +1 +1 +209, 307 +650, 100 +1 +1 +208, 307 +650, 100 +1 +1 +650, 100 +1 +206, 307 +650, 100 +1 +1 +205, 307 +650, 100 +1 +1 +204, 307 +650, 100 +1 +1 +203, 307 +650, 100 +1 +1 +202, 307 +650, 100 +1 +1 +201, 307 +650, 100 +1 +1 +200, 307 +650, 100 +1 +1 +199, 307 +650, 100 +1 +1 +198, 307 +1 +197, 307 +1 +196, 307 +650, 100 +1 +1 +195, 307 +650, 100 +1 +1 +194, 307 +1 +193, 307 +650, 100 +1 +1 +192, 307 +650, 100 +1 +1 +191, 307 +650, 100 +1 +1 +190, 307 +650, 100 +1 +1 +189, 307 +650, 100 +1 +1 +188, 307 +650, 100 +1 +1 +187, 307 +650, 100 +1 +1 +186, 307 +650, 100 +1 +1 +185, 307 +650, 100 +1 +1 +184, 307 +650, 100 +1 +1 +183, 307 +650, 100 +1 +1 +182, 307 +650, 100 +1 +1 +181, 307 +650, 100 +1 +1 +180, 307 +650, 100 +1 +1 +179, 307 +650, 100 +1 +1 +178, 307 +650, 100 +1 +1 +177, 307 +650, 100 +1 +1 +176, 307 +650, 100 +1 +1 +650, 100 +1 +174, 307 +650, 100 +1 +1 +173, 307 +650, 100 +1 +1 +172, 307 +650, 100 +1 +1 +650, 100 +1 +170, 307 +650, 100 +1 +1 +169, 307 +650, 100 +1 +1 +168, 307 +650, 100 +1 +1 +167, 307 +650, 100 +1 +1 +166, 307 +650, 100 +1 +1 +165, 307 +650, 100 +1 +1 +164, 307 +650, 100 +1 +1 +163, 307 +650, 100 +1 +1 +162, 307 +650, 100 +1 +1 +161, 307 +1 +160, 307 +650, 100 +1 +1 +159, 307 +650, 100 +1 +1 +158, 307 +650, 100 +1 +1 +157, 307 +650, 100 +1 +1 +156, 307 +650, 100 +1 +1 +155, 307 +650, 100 +1 +1 +154, 307 +650, 100 +1 +1 +153, 307 +650, 100 +1 +1 +650, 100 +1 +151, 307 +650, 100 +1 +1 +150, 307 +650, 100 +1 +1 +149, 307 +650, 100 +1 +1 +148, 307 +650, 100 +1 +1 +147, 307 +1 +146, 307 +650, 100 +1 +1 +145, 307 +650, 100 +1 +1 +144, 307 +650, 100 +1 +1 +143, 307 +650, 100 +1 +1 +650, 100 +1 +141, 307 +650, 100 +1 +1 +140, 307 +650, 100 +1 +1 +139, 307 +650, 100 +1 +1 +138, 307 +650, 100 +1 +1 +650, 100 +1 +136, 307 +650, 100 +1 +1 +135, 307 +650, 100 +1 +1 +134, 307 +1 +133, 307 +650, 100 +1 +1 +132, 307 +650, 100 +1 +1 +131, 307 +650, 100 +1 +1 +130, 307 +650, 100 +1 +1 +129, 307 +650, 100 +1 +1 +128, 307 +650, 100 +1 +1 +127, 307 +650, 100 +1 +1 +126, 307 +650, 100 +1 +1 +125, 307 +650, 100 +1 +1 +124, 307 +650, 100 +1 +1 +123, 307 +650, 100 +1 +1 +122, 307 +650, 100 +1 +1 +121, 307 +650, 100 +1 +1 +120, 307 +650, 100 +1 +1 +119, 307 +650, 100 +1 +1 +118, 307 +650, 100 +1 +1 +117, 307 +650, 100 +1 +1 +116, 307 +650, 100 +1 +1 +115, 307 +650, 100 +1 +1 +114, 307 +650, 100 +1 +1 +113, 307 +650, 100 +1 +1 +112, 307 +650, 100 +1 +1 +111, 307 +650, 100 +1 +1 +110, 307 +650, 100 +1 +1 +109, 307 +650, 100 +1 +1 +108, 307 +650, 100 +1 +1 +107, 307 +650, 100 +1 +1 +106, 307 +650, 100 +1 +1 +105, 307 +650, 100 +1 +1 +104, 307 +650, 100 +1 +1 +103, 307 +650, 100 +1 +1 +102, 307 +650, 100 +1 +1 +101, 307 +650, 100 +1 +1 +100, 307 +1 +99, 307 +650, 100 +1 +1 +98, 307 +650, 100 +1 +1 +97, 307 +650, 100 +1 +1 +96, 307 +650, 100 +1 +1 +95, 307 +650, 100 +1 +1 +94, 307 +650, 100 +1 +1 +93, 307 +650, 100 +1 +1 +92, 307 +650, 100 +1 +1 +91, 307 +650, 100 +1 +1 +650, 100 +1 +89, 307 +650, 100 +1 +1 +88, 307 +650, 100 +1 +1 +87, 307 +650, 100 +1 +1 +86, 307 +650, 100 +1 +1 +85, 307 +650, 100 +1 +1 +84, 307 +650, 100 +1 +1 +83, 307 +650, 100 +1 +1 +82, 307 +650, 100 +1 +1 +81, 307 +650, 100 +1 +1 +650, 100 +1 +79, 307 +650, 100 +1 +1 +78, 307 +1 +77, 307 +650, 100 +1 +1 +76, 307 +650, 100 +1 +1 +75, 307 +650, 100 +1 +1 +74, 307 +650, 100 +1 +1 +650, 100 +1 +72, 307 +650, 100 +1 +1 +71, 307 +650, 100 +1 +1 +70, 307 +1 +69, 307 +650, 100 +1 +1 +68, 307 +650, 100 +1 +1 +67, 307 +650, 100 +1 +1 +66, 307 +650, 100 +1 +1 +650, 100 +1 +64, 307 +650, 100 +1 +1 +63, 307 +650, 100 +1 +1 +62, 307 +650, 100 +1 +1 +61, 307 +650, 100 +1 +1 +60, 307 +650, 100 +1 +1 +59, 307 +650, 100 +1 +1 +58, 307 +650, 100 +1 +1 +57, 307 +650, 100 +1 +1 +56, 307 +650, 100 +1 +1 +55, 307 +650, 100 +1 +1 +54, 307 +650, 100 +1 +1 +53, 307 +650, 100 +1 +1 +52, 307 +650, 100 +1 +1 +51, 307 +650, 100 +1 +1 +50, 307 +650, 100 +1 +1 +49, 307 +650, 100 +1 +1 +48, 307 +1 +47, 307 +650, 100 +1 +1 +46, 307 +650, 100 +1 +1 +45, 307 +650, 100 +1 +1 +44, 307 +650, 100 +1 +1 +43, 307 +650, 100 +1 +1 +42, 307 +650, 100 +1 +1 +650, 100 +1 +40, 307 +650, 100 +1 +1 +39, 307 +650, 100 +1 +1 +38, 307 +650, 100 +1 +1 +37, 307 +650, 100 +1 +1 +36, 307 +1 +35, 307 +650, 100 +1 +1 +34, 307 +650, 100 +1 +1 +33, 307 +650, 100 +1 +1 +32, 307 +650, 100 +1 +1 +31, 307 +650, 100 +1 +1 +30, 307 +650, 100 +1 +1 +29, 307 +650, 100 +1 +1 +28, 307 +650, 100 +1 +1 +27, 307 +650, 100 +1 +1 +26, 307 +650, 100 +1 +1 +25, 307 +650, 100 +1 +1 +24, 307 +650, 100 +1 +1 +23, 307 +650, 100 +1 +1 +22, 307 +650, 100 +1 +1 +21, 307 +650, 100 +1 +1 +20, 307 +650, 100 +1 +1 +19, 307 +650, 100 +1 +1 +18, 307 +650, 100 +1 +1 +17, 307 +650, 100 +1 +1 +16, 307 +650, 100 +1 +1 +15, 307 +650, 100 +1 +1 +14, 307 +650, 100 +1 +1 +13, 307 +650, 100 +1 +1 +12, 307 +650, 100 +1 +1 +11, 307 +650, 100 +1 +1 +10, 307 +650, 100 +1 +1 +9, 307 +650, 100 +1 +1 +8, 307 +650, 100 +1 +1 +7, 307 +650, 100 +1 +1 +6, 307 +650, 100 +1 +1 +5, 307 +650, 100 +1 +1 +4, 307 +650, 100 +1 +1 +3, 307 +650, 100 +1 +1 +2, 307 +650, 100 +1 +1 +1, 307 +650, 100 +1 +1 +0, 307 +650, 100 +1 +1 +799, 446 +650, 100 +1 +1 +798, 446 +650, 100 +1 +1 +797, 446 +650, 100 +1 +1 +796, 446 +650, 100 +1 +1 +795, 446 +650, 100 +1 +1 +794, 446 +650, 100 +1 +1 +793, 446 +650, 100 +1 +1 +792, 446 +650, 100 +1 +1 +790, 446 +650, 100 +1 +1 +789, 446 +650, 100 +1 +1 +788, 446 +650, 100 +1 +1 +787, 446 +650, 100 +1 +1 +650, 100 +1 +785, 446 +650, 100 +1 +1 +784, 446 +650, 100 +1 +1 +783, 446 +650, 100 +1 +1 +782, 446 +1 +781, 446 +650, 100 +1 +1 +780, 446 +650, 100 +1 +1 +779, 446 +650, 100 +1 +1 +778, 446 +650, 100 +1 +1 +777, 446 +650, 100 +1 +1 +776, 446 +650, 100 +1 +1 +775, 446 +650, 100 +1 +1 +774, 446 +650, 100 +1 +1 +773, 446 +650, 100 +1 +1 +772, 446 +650, 100 +1 +1 +771, 446 +650, 100 +1 +1 +770, 446 +1 +769, 446 +650, 100 +1 +1 +768, 446 +650, 100 +1 +1 +650, 100 +1 +766, 446 +650, 100 +1 +1 +765, 446 +650, 100 +1 +1 +764, 446 +650, 100 +1 +1 +763, 446 +650, 100 +1 +1 +762, 446 +650, 100 +1 +1 +761, 446 +650, 100 +1 +1 +760, 446 +650, 100 +1 +1 +759, 446 +650, 100 +1 +1 +758, 446 +650, 100 +1 +1 +757, 446 +650, 100 +1 +1 +756, 446 +650, 100 +1 +1 +755, 446 +650, 100 +1 +1 +754, 446 +650, 100 +1 +1 +753, 446 +650, 100 +1 +1 +752, 446 +650, 100 +1 +1 +751, 446 +1 +750, 446 +650, 100 +1 +1 +749, 446 +650, 100 +1 +1 +748, 446 +650, 100 +1 +1 +747, 446 +650, 100 +1 +1 +746, 446 +650, 100 +1 +1 +650, 100 +1 +744, 446 +650, 100 +1 +1 +743, 446 +650, 100 +1 +1 +742, 446 +650, 100 +1 +1 +650, 100 +1 +740, 446 +1 +739, 446 +650, 100 +1 +1 +738, 446 +1 +737, 446 +650, 100 +1 +1 +736, 446 +650, 100 +1 +1 +735, 446 +650, 100 +1 +1 +734, 446 +650, 100 +1 +1 +733, 446 +650, 100 +1 +1 +732, 446 +650, 100 +1 +1 +731, 446 +650, 100 +1 +1 +730, 446 +650, 100 +1 +1 +729, 446 +650, 100 +1 +1 +728, 446 +650, 100 +1 +1 +727, 446 +650, 100 +1 +1 +726, 446 +650, 100 +1 +1 +725, 446 +650, 100 +1 +1 +724, 446 +1 +723, 446 +650, 100 +1 +1 +722, 446 +650, 100 +1 +1 +721, 446 +650, 100 +1 +1 +720, 446 +650, 100 +1 +1 +719, 446 +650, 100 +1 +1 +718, 446 +1 +717, 446 +650, 100 +1 +1 +716, 446 +650, 100 +1 +1 +715, 446 +1 +714, 446 +650, 100 +1 +1 +713, 446 +650, 100 +1 +1 +712, 446 +650, 100 +1 +1 +711, 446 +650, 100 +1 +1 +710, 446 +650, 100 +1 +1 +709, 446 +650, 100 +1 +1 +708, 446 +650, 100 +1 +1 +707, 446 +650, 100 +1 +1 +706, 446 +650, 100 +1 +1 +705, 446 +650, 100 +1 +1 +704, 446 +650, 100 +1 +1 +703, 446 +650, 100 +1 +1 +702, 446 +650, 100 +1 +1 +701, 446 +650, 100 +1 +1 +700, 446 +650, 100 +1 +1 +650, 100 +1 +698, 446 +650, 100 +1 +1 +697, 446 +650, 100 +1 +1 +696, 446 +650, 100 +1 +1 +695, 446 +650, 100 +1 +1 +694, 446 +650, 100 +1 +1 +693, 446 +650, 100 +1 +1 +650, 100 +1 +691, 446 +650, 100 +1 +1 +690, 446 +650, 100 +1 +1 +689, 446 +650, 107 +1 +1 +688, 446 +650, 107 +1 +1 +650, 107 +1 +686, 446 +650, 107 +1 +1 +685, 446 +650, 107 +1 +1 +684, 446 +650, 107 +1 +1 +683, 446 +1 +682, 446 +650, 107 +1 +1 +365, 313 +681, 446 +1 +1 +coin packet received +9 +650, 107 +680, 446 +1 +1 +650, 107 +679, 446 +1 +1 +678, 446 +650, 107 +1 +1 +677, 446 +650, 107 +1 +1 +676, 446 +650, 114 +1 +1 +675, 446 +650, 114 +1 +1 +674, 446 +650, 114 +1 +1 +673, 446 +650, 114 +1 +1 +672, 446 +650, 114 +1 +1 +671, 446 +650, 114 +1 +1 +670, 446 +650, 114 +1 +1 +669, 446 +1 +668, 446 +650, 114 +1 +1 +667, 446 +650, 114 +1 +1 +666, 446 +650, 114 +1 +1 +665, 446 +650, 114 +1 +1 +664, 446 +1 +663, 446 +650, 114 +1 +1 +662, 446 +650, 114 +1 +1 +661, 446 +650, 114 +1 +1 +660, 446 +650, 114 +1 +1 +659, 446 +650, 114 +1 +1 +658, 446 +650, 114 +1 +1 +657, 446 +650, 114 +1 +1 +656, 446 +650, 114 +1 +1 +655, 446 +1 +654, 446 +650, 114 +1 +1 +653, 446 +650, 114 +1 +1 +652, 446 +650, 114 +1 +1 +651, 446 +1 +650, 446 +650, 114 +1 +1 +649, 446 +650, 114 +1 +1 +648, 446 +650, 114 +1 +1 +647, 446 +650, 114 +1 +1 +646, 446 +650, 114 +1 +1 +645, 446 +650, 114 +1 +1 +644, 446 +650, 114 +1 +1 +643, 446 +650, 114 +1 +1 +642, 446 +650, 114 +1 +1 +641, 446 +650, 114 +1 +1 +640, 446 +650, 114 +1 +1 +639, 446 +650, 114 +1 +1 +638, 446 +650, 114 +1 +1 +637, 446 +650, 114 +1 +1 +636, 446 +650, 114 +1 +1 +635, 446 +650, 114 +1 +1 +650, 114 +1 +633, 446 +650, 114 +1 +1 +650, 114 +1 +631, 446 +650, 114 +1 +1 +630, 446 +650, 114 +1 +1 +629, 446 +650, 114 +1 +1 +628, 446 +650, 114 +1 +1 +627, 446 +650, 114 +1 +1 +626, 446 +650, 114 +1 +1 +625, 446 +650, 114 +1 +1 +624, 446 +650, 114 +1 +1 +623, 446 +650, 114 +1 +1 +622, 446 +650, 114 +1 +1 +621, 446 +650, 114 +1 +1 +620, 446 +650, 114 +1 +1 +619, 446 +650, 114 +1 +1 +618, 446 +650, 114 +1 +1 +617, 446 +650, 114 +1 +1 +616, 446 +650, 114 +1 +1 +650, 114 +1 +614, 446 +650, 114 +1 +1 +613, 446 +650, 114 +1 +1 +612, 446 +650, 114 +1 +1 +650, 114 +1 +610, 446 +650, 114 +1 +1 +609, 446 +650, 114 +1 +1 +608, 446 +650, 114 +1 +1 +607, 446 +650, 114 +1 +1 +606, 446 +650, 114 +1 +1 +605, 446 +650, 114 +1 +1 +650, 114 +1 +650, 114 +1 +650, 114 +1 +650, 114 +1 +600, 446 +650, 114 +1 +1 +599, 446 +650, 114 +1 +1 +598, 446 +650, 114 +1 +1 +597, 446 +650, 114 +1 +1 +596, 446 +650, 114 +1 +1 +595, 446 +650, 114 +1 +1 +594, 446 +1 +593, 446 +1 +592, 446 +650, 114 +1 +1 +591, 446 +650, 114 +1 +1 +590, 446 +650, 114 +1 +1 +650, 114 +1 +588, 446 +650, 114 +1 +1 +587, 446 +650, 114 +1 +1 +586, 446 +650, 114 +1 +1 +585, 446 +650, 114 +1 +1 +584, 446 +650, 114 +1 +1 +583, 446 +650, 114 +1 +1 +582, 446 +650, 114 +1 +1 +581, 446 +650, 114 +1 +1 +580, 446 +650, 114 +1 +1 +579, 446 +650, 114 +1 +1 +578, 446 +650, 114 +1 +1 +577, 446 +1 +576, 446 +650, 114 +1 +1 +575, 446 +650, 114 +1 +1 +574, 446 +650, 114 +1 +1 +573, 446 +650, 114 +1 +1 +572, 446 +1 +571, 446 +650, 114 +1 +1 +650, 114 +1 +569, 446 +650, 114 +1 +1 +568, 446 +650, 114 +1 +1 +567, 446 +650, 114 +1 +1 +566, 446 +650, 114 +1 +1 +565, 446 +650, 114 +1 +1 +564, 446 +650, 114 +1 +1 +563, 446 +650, 114 +1 +1 +562, 446 +650, 114 +1 +1 +561, 446 +1 +560, 446 +650, 114 +1 +1 +559, 446 +650, 114 +1 +1 +558, 446 +650, 114 +1 +1 +557, 446 +650, 114 +1 +1 +556, 446 +650, 114 +1 +1 +555, 446 +650, 114 +1 +1 +554, 446 +650, 114 +1 +1 +553, 446 +650, 114 +1 +1 +552, 446 +650, 114 +1 +1 +551, 446 +650, 114 +1 +1 +550, 446 +650, 114 +1 +1 +650, 114 +1 +548, 446 +650, 114 +1 +1 +547, 446 +650, 114 +1 +1 +546, 446 +650, 114 +1 +1 +545, 446 +650, 114 +1 +1 +544, 446 +650, 114 +1 +1 +543, 446 +1 +542, 446 +650, 114 +1 +1 +541, 446 +650, 114 +1 +1 +650, 114 +1 +539, 446 +650, 114 +1 +1 +538, 446 +650, 114 +1 +1 +537, 446 +650, 114 +1 +1 +536, 446 +650, 114 +1 +1 +535, 446 +650, 114 +1 +1 +534, 446 +650, 114 +1 +1 +533, 446 +650, 114 +1 +1 +532, 446 +650, 114 +1 +1 +531, 446 +650, 114 +1 +1 +530, 446 +650, 114 +1 +1 +650, 114 +1 +528, 446 +650, 114 +1 +1 +527, 446 +650, 114 +1 +1 +526, 446 +650, 114 +1 +1 +525, 446 +650, 114 +1 +1 +524, 446 +650, 114 +1 +1 +523, 446 +650, 114 +1 +1 +522, 446 +650, 114 +1 +1 +521, 446 +650, 114 +1 +1 +520, 446 +650, 114 +1 +1 +519, 446 +650, 114 +1 +1 +518, 446 +650, 114 +1 +1 +517, 446 +650, 114 +1 +1 +516, 446 +650, 114 +1 +1 +515, 446 +650, 114 +1 +1 +650, 114 +1 +513, 446 +650, 114 +1 +1 +512, 446 +650, 114 +1 +1 +650, 114 +1 +510, 446 +650, 114 +1 +1 +509, 446 +650, 114 +1 +1 +508, 446 +650, 114 +1 +1 +507, 446 +650, 114 +1 +1 +506, 446 +650, 114 +1 +1 +505, 446 +650, 114 +1 +1 +504, 446 +650, 114 +1 +1 +503, 446 +650, 114 +1 +1 +502, 446 +1 +501, 446 +650, 114 +1 +1 +500, 446 +650, 114 +1 +1 +499, 446 +650, 114 +1 +1 +498, 446 +650, 114 +1 +1 +497, 446 +650, 114 +1 +1 +496, 446 +650, 114 +1 +1 +495, 446 +650, 114 +1 +1 +494, 446 +650, 114 +1 +1 +493, 446 +650, 114 +1 +1 +492, 446 +650, 114 +1 +1 +491, 446 +650, 114 +1 +1 +490, 446 +650, 114 +1 +1 +489, 446 +1 +488, 446 +650, 114 +1 +1 +487, 446 +650, 114 +1 +1 +486, 446 +650, 114 +1 +1 +485, 446 +650, 114 +1 +1 +484, 446 +650, 114 +1 +1 +483, 446 +650, 114 +1 +1 +482, 446 +650, 114 +1 +1 +481, 446 +650, 114 +1 +1 +480, 446 +650, 114 +1 +1 +479, 446 +650, 114 +1 +1 +478, 446 +650, 114 +1 +1 +477, 446 +650, 114 +1 +1 +476, 446 +650, 114 +1 +1 +475, 446 +650, 114 +1 +1 +474, 446 +650, 114 +1 +1 +473, 446 +1 +472, 446 +650, 114 +1 +1 +471, 446 +650, 114 +1 +1 +470, 446 +650, 114 +1 +1 +469, 446 +650, 114 +1 +1 +468, 446 +650, 114 +1 +1 +467, 446 +650, 114 +1 +1 +466, 446 +650, 114 +1 +1 +465, 446 +650, 114 +1 +1 +464, 446 +650, 114 +1 +1 +463, 446 +650, 114 +1 +1 +462, 446 +650, 114 +1 +1 +461, 446 +650, 114 +1 +1 +460, 446 +650, 114 +1 +1 +459, 446 +650, 114 +1 +1 +458, 446 +650, 114 +1 +1 +457, 446 +650, 114 +1 +1 +456, 446 +650, 114 +1 +1 +455, 446 +650, 114 +1 +1 +454, 446 +650, 114 +1 +1 +453, 446 +650, 114 +1 +1 +452, 446 +650, 114 +1 +1 +451, 446 +650, 114 +1 +1 +450, 446 +650, 114 +1 +1 +449, 446 +650, 114 +1 +1 +448, 446 +650, 114 +1 +1 +447, 446 +650, 114 +1 +1 +446, 446 +650, 114 +1 +1 +445, 446 +650, 114 +1 +1 +444, 446 +650, 114 +1 +1 +443, 446 +650, 114 +1 +1 +442, 446 +650, 114 +1 +1 +441, 446 +650, 114 +1 +1 +440, 446 +650, 114 +1 +1 +439, 446 +650, 114 +1 +1 +438, 446 +650, 114 +1 +1 +437, 446 +650, 114 +1 +1 +436, 446 +650, 114 +1 +1 +435, 446 +650, 114 +1 +1 +434, 446 +650, 114 +1 +1 +433, 446 +650, 114 +1 +1 +432, 446 +650, 114 +1 +1 +431, 446 +650, 114 +1 +1 +430, 446 +650, 114 +1 +1 +429, 446 +650, 114 +1 +1 +428, 446 +650, 114 +1 +1 +427, 446 +650, 114 +1 +1 +426, 446 +650, 114 +1 +1 +650, 114 +1 +424, 446 +650, 114 +1 +1 +423, 446 +650, 114 +1 +1 +422, 446 +650, 114 +1 +1 +421, 446 +650, 114 +1 +1 +420, 446 +650, 114 +1 +1 +419, 446 +650, 114 +1 +1 +418, 446 +650, 114 +1 +1 +417, 446 +650, 114 +1 +1 +416, 446 +1 +415, 446 +650, 114 +1 +1 +414, 446 +650, 114 +1 +1 +413, 446 +650, 114 +1 +1 +412, 446 +650, 114 +1 +1 +411, 446 +1 +410, 446 +650, 114 +1 +1 +409, 446 +650, 114 +1 +1 +408, 446 +1 +407, 446 +650, 114 +1 +1 +406, 446 +650, 114 +1 +1 +405, 446 +650, 114 +1 +1 +404, 446 +650, 114 +1 +1 +403, 446 +650, 114 +1 +1 +402, 446 +650, 114 +1 +1 +401, 446 +650, 114 +1 +1 +400, 446 +650, 114 +1 +1 +399, 446 +650, 114 +1 +1 +398, 446 +1 +397, 446 +1 +396, 446 +650, 114 +1 +1 +395, 446 +650, 114 +1 +1 +394, 446 +650, 114 +1 +1 +393, 446 +650, 114 +1 +1 +392, 446 +650, 114 +1 +1 +391, 446 +650, 114 +1 +1 +390, 446 +650, 114 +1 +1 +389, 446 +650, 114 +1 +1 +388, 446 +650, 114 +1 +1 +387, 446 +650, 114 +1 +1 +386, 446 +650, 114 +1 +1 +385, 446 +650, 114 +1 +1 +384, 446 +650, 114 +1 +1 +383, 446 +650, 114 +1 +1 +650, 114 +1 +381, 446 +650, 114 +1 +1 +380, 446 +650, 114 +1 +1 +379, 446 +650, 114 +1 +1 +378, 446 +650, 114 +1 +1 +377, 446 +650, 114 +1 +1 +376, 446 +650, 114 +1 +1 +375, 446 +650, 114 +1 +1 +374, 446 +650, 114 +1 +1 +373, 446 +1 +372, 446 +650, 114 +1 +1 +371, 446 +650, 114 +1 +1 +370, 446 +650, 114 +1 +1 +369, 446 +650, 114 +1 +1 +368, 446 +650, 114 +1 +1 +367, 446 +650, 114 +1 +1 +366, 446 +650, 114 +1 +1 +365, 446 +650, 114 +1 +1 +364, 446 +650, 114 +1 +1 +363, 446 +650, 114 +1 +1 +362, 446 +650, 114 +1 +1 +361, 446 +650, 114 +1 +1 +360, 446 +650, 114 +1 +1 +359, 446 +650, 114 +1 +1 +358, 446 +650, 114 +1 +1 +357, 446 +650, 114 +1 +1 +356, 446 +650, 114 +1 +1 +355, 446 +650, 114 +1 +1 +354, 446 +650, 114 +1 +1 +353, 446 +650, 114 +1 +1 +352, 446 +650, 114 +1 +1 +351, 446 +650, 114 +1 +1 +350, 446 +650, 114 +1 +1 +349, 446 +650, 114 +1 +1 +348, 446 +1 +347, 446 +650, 114 +1 +1 +346, 446 +650, 114 +1 +1 +345, 446 +650, 114 +1 +1 +344, 446 +650, 114 +1 +1 +343, 446 +650, 114 +1 +1 +342, 446 +650, 114 +1 +1 +341, 446 +650, 114 +1 +1 +340, 446 +650, 114 +1 +1 +339, 446 +650, 114 +1 +1 +338, 446 +650, 114 +1 +1 +337, 446 +650, 114 +1 +1 +336, 446 +650, 114 +1 +1 +335, 446 +650, 114 +1 +1 +334, 446 +650, 114 +1 +1 +333, 446 +650, 114 +1 +1 +332, 446 +650, 114 +1 +1 +331, 446 +650, 114 +1 +1 +330, 446 +650, 114 +1 +1 +650, 114 +1 +328, 446 +650, 114 +1 +1 +327, 446 +650, 114 +1 +1 +326, 446 +650, 114 +1 +1 +325, 446 +650, 114 +1 +1 +324, 446 +650, 114 +1 +1 +323, 446 +650, 114 +1 +1 +322, 446 +650, 114 +1 +1 +321, 446 +650, 114 +1 +1 +320, 446 +650, 114 +1 +1 +319, 446 +650, 114 +1 +1 +318, 446 +650, 114 +1 +1 +317, 446 +650, 114 +1 +1 +316, 446 +650, 114 +1 +1 +315, 446 +650, 114 +1 +1 +314, 446 +650, 114 +1 +1 +313, 446 +650, 114 +1 +1 +312, 446 +650, 114 +1 +1 +311, 446 +650, 114 +1 +1 +310, 446 +650, 114 +1 +1 +309, 446 +650, 114 +1 +1 +308, 446 +650, 114 +1 +1 +307, 446 +650, 114 +1 +1 +306, 446 +650, 114 +1 +1 +305, 446 +650, 114 +1 +1 +304, 446 +650, 114 +1 +1 +303, 446 +650, 114 +1 +1 +302, 446 +650, 114 +1 +1 +301, 446 +650, 114 +1 +1 +650, 114 +1 +650, 114 +1 +298, 446 +650, 114 +1 +1 +297, 446 +650, 114 +1 +1 +296, 446 +650, 114 +1 +1 +295, 446 +650, 114 +1 +1 +294, 446 +650, 114 +1 +1 +293, 446 +1 +292, 446 +650, 114 +1 +1 +291, 446 +650, 114 +1 +1 +290, 446 +650, 114 +1 +1 +289, 446 +650, 114 +1 +1 +288, 446 +650, 114 +1 +1 +287, 446 +650, 114 +1 +1 +286, 446 +650, 114 +1 +1 +285, 446 +1 +284, 446 +650, 114 +1 +1 +283, 446 +650, 114 +1 +1 +282, 446 +650, 114 +1 +1 +281, 446 +650, 114 +1 +1 +280, 446 +1 +279, 446 +650, 114 +1 +1 +278, 446 +650, 114 +1 +1 +277, 446 +650, 114 +1 +1 +276, 446 +650, 114 +1 +1 +275, 446 +650, 114 +1 +1 +274, 446 +650, 114 +1 +1 +273, 446 +650, 114 +1 +1 +272, 446 +650, 114 +1 +1 +271, 446 +650, 114 +1 +1 +270, 446 +650, 114 +1 +1 +269, 446 +650, 114 +1 +1 +268, 446 +650, 114 +1 +1 +267, 446 +650, 114 +1 +1 +266, 446 +650, 114 +1 +1 +265, 446 +650, 114 +1 +1 +264, 446 +650, 114 +1 +1 +263, 446 +650, 114 +1 +1 +262, 446 +650, 114 +1 +1 +261, 446 +650, 114 +1 +1 +260, 446 +650, 114 +1 +1 +259, 446 +650, 114 +1 +1 +258, 446 +650, 114 +1 +1 +257, 446 +650, 114 +1 +1 +256, 446 +650, 114 +1 +1 +255, 446 +650, 114 +1 +1 +254, 446 +650, 114 +1 +1 +253, 446 +650, 114 +1 +1 +252, 446 +650, 114 +1 +1 +251, 446 +650, 114 +1 +1 +250, 446 +650, 114 +1 +1 +249, 446 +650, 114 +1 +1 +248, 446 +650, 114 +1 +1 +247, 446 +650, 114 +1 +1 +246, 446 +650, 114 +1 +1 +245, 446 +650, 114 +1 +1 +244, 446 +650, 114 +1 +1 +243, 446 +650, 114 +1 +1 +242, 446 +650, 114 +1 +1 +241, 446 +650, 114 +1 +1 +240, 446 +1 +239, 446 +650, 114 +1 +1 +238, 446 +650, 114 +1 +1 +237, 446 +650, 114 +1 +1 +236, 446 +650, 114 +1 +1 +235, 446 +650, 114 +1 +1 +234, 446 +650, 114 +1 +1 +233, 446 +650, 114 +1 +1 +231, 446 +650, 114 +1 +1 +230, 446 +650, 114 +1 +1 +229, 446 +650, 114 +1 +1 +228, 446 +650, 114 +1 +1 +227, 446 +1 +226, 446 +650, 114 +1 +1 +225, 446 +650, 114 +1 +1 +224, 446 +650, 114 +1 +1 +223, 446 +650, 114 +1 +1 +222, 446 +650, 114 +1 +1 +221, 446 +1 +220, 446 +650, 114 +1 +1 +219, 446 +650, 114 +1 +1 +218, 446 +650, 114 +1 +1 +217, 446 +650, 114 +1 +1 +216, 446 +650, 114 +1 +1 +215, 446 +650, 114 +1 +1 +214, 446 +650, 114 +1 +1 +213, 446 +650, 114 +1 +1 +212, 446 +650, 114 +1 +1 +211, 446 +650, 114 +1 +1 +210, 446 +650, 114 +1 +1 +209, 446 +650, 114 +1 +1 +208, 446 +1 +207, 446 +650, 114 +1 +1 +206, 446 +650, 114 +1 +1 +205, 446 +650, 114 +1 +1 +204, 446 +650, 114 +1 +1 +203, 446 +650, 114 +1 +1 +202, 446 +650, 114 +1 +1 +201, 446 +650, 114 +1 +1 +200, 446 +650, 114 +1 +1 +199, 446 +650, 114 +1 +1 +198, 446 +650, 114 +1 +1 +197, 446 +650, 114 +1 +1 +196, 446 +650, 114 +1 +1 +195, 446 +650, 114 +1 +1 +194, 446 +650, 114 +1 +1 +193, 446 +650, 114 +1 +1 +192, 446 +650, 114 +1 +1 +191, 446 +650, 114 +1 +1 +650, 114 +1 +189, 446 +650, 114 +1 +1 +188, 446 +650, 114 +1 +1 +187, 446 +1 +186, 446 +650, 114 +1 +1 +650, 114 +1 +184, 446 +650, 114 +1 +1 +183, 446 +650, 114 +1 +1 +182, 446 +650, 114 +1 +1 +181, 446 +650, 114 +1 +1 +180, 446 +650, 114 +1 +1 +179, 446 +650, 114 +1 +1 +178, 446 +650, 114 +1 +1 +650, 114 +1 +176, 446 +650, 114 +1 +1 +175, 446 +650, 114 +1 +1 +174, 446 +650, 114 +1 +1 +173, 446 +650, 114 +1 +1 +172, 446 +650, 114 +1 +1 +171, 446 +650, 114 +1 +1 +170, 446 +650, 114 +1 +1 +169, 446 +650, 114 +1 +1 +168, 446 +650, 114 +1 +1 +167, 446 +650, 114 +1 +1 +166, 446 +650, 114 +1 +1 +165, 446 +650, 114 +1 +1 +164, 446 +650, 114 +1 +1 +163, 446 +650, 114 +1 +1 +162, 446 +650, 114 +1 +1 +161, 446 +1 +160, 446 +650, 114 +1 +1 +159, 446 +650, 114 +1 +1 +158, 446 +650, 114 +1 +1 +157, 446 +650, 114 +1 +1 +156, 446 +650, 114 +1 +1 +155, 446 +650, 114 +1 +1 +154, 446 +650, 114 +1 +1 +153, 446 +650, 114 +1 +1 +152, 446 +650, 114 +1 +1 +151, 446 +650, 114 +1 +1 +150, 446 +650, 114 +1 +1 +149, 446 +650, 114 +1 +1 +148, 446 +650, 114 +1 +1 +650, 114 +1 +146, 446 +650, 114 +1 +1 +145, 446 +650, 114 +1 +1 +144, 446 +650, 114 +1 +1 +143, 446 +650, 114 +1 +1 +142, 446 +650, 114 +1 +1 +141, 446 +650, 114 +1 +1 +140, 446 +650, 114 +1 +1 +139, 446 +650, 114 +1 +1 +138, 446 +650, 114 +1 +1 +137, 446 +650, 114 +1 +1 +136, 446 +650, 114 +1 +1 +135, 446 +650, 114 +1 +1 +134, 446 +650, 114 +1 +1 +133, 446 +650, 114 +1 +1 +132, 446 +650, 114 +1 +1 +131, 446 +650, 114 +1 +1 +130, 446 +650, 114 +1 +1 +129, 446 +1 +128, 446 +650, 114 +1 +1 +127, 446 +650, 114 +1 +1 +126, 446 +650, 114 +1 +1 +125, 446 +650, 114 +1 +1 +124, 446 +1 +123, 446 +1 +122, 446 +650, 114 +1 +1 +121, 446 +650, 114 +1 +1 +120, 446 +650, 114 +1 +1 +119, 446 +650, 114 +1 +1 +118, 446 +650, 114 +1 +1 +117, 446 +650, 114 +1 +1 +116, 446 +650, 114 +1 +1 +115, 446 +650, 114 +1 +1 +114, 446 +650, 114 +1 +1 +113, 446 +650, 114 +1 +1 +112, 446 +650, 114 +1 +1 +111, 446 +650, 114 +1 +1 +110, 446 +650, 114 +1 +1 +650, 114 +1 +108, 446 +650, 114 +1 +1 +107, 446 +650, 114 +1 +1 +106, 446 +650, 114 +1 +1 +105, 446 +650, 114 +1 +1 +104, 446 +650, 114 +1 +1 +103, 446 +650, 114 +1 +1 +102, 446 +650, 114 +1 +1 +101, 446 +650, 114 +1 +1 +100, 446 +650, 114 +1 +1 +99, 446 +650, 114 +1 +1 +98, 446 +650, 114 +1 +1 +97, 446 +1 +96, 446 +650, 114 +1 +1 +95, 446 +650, 114 +1 +1 +94, 446 +650, 114 +1 +1 +93, 446 +650, 114 +1 +1 +650, 114 +1 +91, 446 +650, 114 +1 +1 +90, 446 +650, 114 +1 +1 +89, 446 +650, 114 +1 +1 +88, 446 +650, 114 +1 +1 +87, 446 +650, 114 +1 +1 +86, 446 +650, 114 +1 +1 +85, 446 +650, 114 +1 +1 +84, 446 +650, 114 +1 +1 +83, 446 +650, 114 +1 +1 +82, 446 +650, 114 +1 +1 +81, 446 +650, 114 +1 +1 +80, 446 +650, 114 +1 +1 +79, 446 +650, 114 +1 +1 +78, 446 +650, 114 +1 +1 +77, 446 +650, 114 +1 +1 +76, 446 +650, 114 +1 +1 +75, 446 +650, 114 +1 +1 +74, 446 +650, 114 +1 +1 +73, 446 +650, 114 +1 +1 +72, 446 +650, 114 +1 +1 +71, 446 +650, 114 +1 +1 +650, 114 +1 +69, 446 +650, 114 +1 +1 +68, 446 +650, 114 +1 +1 +67, 446 +650, 114 +1 +1 +66, 446 +650, 114 +1 +1 +65, 446 +650, 114 +1 +1 +64, 446 +650, 114 +1 +1 +63, 446 +650, 114 +1 +1 +62, 446 +650, 114 +1 +1 +61, 446 +650, 114 +1 +1 +60, 446 +650, 114 +1 +1 +59, 446 +650, 114 +1 +1 +58, 446 +650, 114 +1 +1 +57, 446 +650, 114 +1 +1 +56, 446 +650, 114 +1 +1 +55, 446 +650, 114 +1 +1 +54, 446 +650, 114 +1 +1 +53, 446 +650, 114 +1 +1 +52, 446 +650, 114 +1 +1 +51, 446 +650, 114 +1 +1 +50, 446 +1 +49, 446 +650, 114 +1 +1 +48, 446 +650, 114 +1 +1 +47, 446 +650, 114 +1 +1 +46, 446 +650, 114 +1 +1 +650, 114 +1 +44, 446 +650, 114 +1 +1 +43, 446 +650, 114 +1 +1 +42, 446 +650, 114 +1 +1 +41, 446 +650, 114 +1 +1 +40, 446 +650, 114 +1 +1 +39, 446 +650, 114 +1 +1 +38, 446 +650, 114 +1 +1 +37, 446 +650, 114 +1 +1 +36, 446 +650, 114 +1 +1 +35, 446 +650, 114 +1 +1 +34, 446 +650, 114 +1 +1 +33, 446 +1 +32, 446 +650, 114 +1 +1 +31, 446 +650, 114 +1 +1 +30, 446 +650, 114 +1 +1 +650, 114 +1 +28, 446 +650, 114 +1 +1 +27, 446 +650, 114 +1 +1 +26, 446 +650, 114 +1 +1 +25, 446 +650, 114 +1 +1 +24, 446 +650, 114 +1 +1 +23, 446 +650, 114 +1 +1 +22, 446 +650, 114 +1 +1 +21, 446 +650, 114 +1 +1 +20, 446 +650, 114 +1 +1 +19, 446 +650, 114 +1 +1 +18, 446 +650, 114 +1 +1 +17, 446 +650, 114 +1 +1 +16, 446 +650, 114 +1 +1 +15, 446 +1 +14, 446 +650, 114 +1 +1 +13, 446 +650, 114 +1 +1 +12, 446 +650, 114 +1 +1 +11, 446 +650, 114 +1 +1 +10, 446 +650, 114 +1 +1 +9, 446 +650, 114 +1 +1 +8, 446 +650, 114 +1 +1 +7, 446 +650, 114 +1 +1 +6, 446 +650, 114 +1 +1 +5, 446 +650, 114 +1 +1 +4, 446 +1 +650, 114 +1 +2, 446 +650, 114 +1 +1 +1, 446 +1 +0, 446 +650, 114 +1 +1 +650, 114 +1 +798, 419 +650, 114 +1 +1 +797, 419 +650, 114 +1 +1 +796, 419 +650, 114 +1 +1 +795, 419 +650, 114 +1 +1 +794, 419 +650, 114 +1 +1 +793, 419 +650, 114 +1 +1 +650, 114 +1 +791, 419 +1 +790, 419 +650, 114 +1 +1 +789, 419 +650, 114 +1 +1 +788, 419 +650, 114 +1 +1 +787, 419 +650, 114 +1 +1 +785, 419 +650, 114 +1 +1 +650, 114 +1 +783, 419 +650, 114 +1 +1 +782, 419 +650, 114 +1 +1 +781, 419 +650, 114 +1 +1 +780, 419 +650, 114 +1 +1 +779, 419 +650, 114 +1 +1 +778, 419 +650, 114 +1 +1 +777, 419 +650, 114 +1 +1 +776, 419 +650, 114 +1 +1 +775, 419 +650, 114 +1 +1 +774, 419 +650, 114 +1 +1 +773, 419 +650, 114 +1 +1 +772, 419 +650, 114 +1 +1 +771, 419 +1 +770, 419 +650, 114 +1 +1 +650, 114 +1 +768, 419 +650, 114 +1 +1 +767, 419 +650, 114 +1 +1 +766, 419 +650, 114 +1 +1 +765, 419 +650, 114 +1 +1 +764, 419 +650, 114 +1 +1 +763, 419 +650, 114 +1 +1 +762, 419 +1 +761, 419 +1 +760, 419 +650, 114 +1 +1 +759, 419 +650, 114 +1 +1 +758, 419 +650, 114 +1 +1 +757, 419 +650, 114 +1 +1 +756, 419 +650, 114 +1 +1 +755, 419 +650, 114 +1 +1 +754, 419 +650, 114 +1 +1 +753, 419 +650, 114 +1 +1 +752, 419 +1 +751, 419 +650, 114 +1 +1 +750, 419 +650, 114 +1 +1 +749, 419 +650, 114 +1 +1 +748, 419 +650, 114 +1 +1 +747, 419 +650, 114 +1 +1 +746, 419 +650, 114 +1 +1 +745, 419 +650, 114 +1 +1 +744, 419 +650, 114 +1 +1 +742, 419 +650, 114 +1 +1 +650, 114 +1 +740, 419 +650, 114 +1 +1 +739, 419 +1 +738, 419 +650, 114 +1 +1 +737, 419 +650, 114 +1 +1 +650, 114 +1 +735, 419 +1 +734, 419 +650, 114 +1 +1 +733, 419 +650, 114 +1 +1 +732, 419 +650, 114 +1 +1 +731, 419 +650, 114 +1 +1 +650, 114 +1 +729, 419 +650, 114 +1 +1