From ced3d03bdb3ce866d832e03fb212865140905a9a Mon Sep 17 00:00:00 2001 From: Thomas Leyh Date: Sun, 24 Jul 2016 08:14:18 +0200 Subject: Add project files. --- V3/AI/ActionState.cs | 25 + V3/AI/AiState.cs | 27 + V3/AI/IAction.cs | 24 + V3/AI/IAiPlayer.cs | 51 + V3/AI/IStrategy.cs | 17 + V3/AI/IWorldView.cs | 21 + V3/AI/Internal/AbstractAction.cs | 38 + V3/AI/Internal/AiPlayer.cs | 244 ++++ V3/AI/Internal/AttackStrategy.cs | 48 + V3/AI/Internal/IActionFactory.cs | 27 + V3/AI/Internal/MoveAction.cs | 53 + V3/AI/Internal/SpawnAction.cs | 42 + V3/AI/Internal/WorldView.cs | 19 + V3/AchievementsAndStatistics.cs | 31 + V3/Bindings.cs | 75 ++ V3/CONTROLS.md | 37 + V3/CREDITS.md | 51 + V3/Camera/CameraCentered.cs | 57 + V3/Camera/CameraManager.cs | 71 ++ V3/Camera/CameraScrolling.cs | 96 ++ V3/Camera/CameraType.cs | 8 + V3/Camera/ICamera.cs | 18 + V3/ClassDiagram1.cd | 2 + V3/Content/Buttons/Button-01.png | Bin 0 -> 99135 bytes V3/Content/Buttons/Button-01_Pressed.png | Bin 0 -> 112006 bytes V3/Content/Buttons/Button-02.png | Bin 0 -> 55248 bytes V3/Content/Buttons/Button-02_Pressed.png | Bin 0 -> 66371 bytes V3/Content/Buttons/Button-03.png | Bin 0 -> 64359 bytes V3/Content/Buttons/Button-03_Pressed.png | Bin 0 -> 75343 bytes V3/Content/Buttons/Button-04.png | Bin 0 -> 56617 bytes V3/Content/Buttons/Button-04_Pressed.png | Bin 0 -> 67959 bytes V3/Content/Buttons/Button-05.png | Bin 0 -> 70658 bytes V3/Content/Buttons/Button-05_Pressed.png | Bin 0 -> 82438 bytes V3/Content/Buttons/Button-06.png | Bin 0 -> 54510 bytes V3/Content/Buttons/Button-06_Pressed.png | Bin 0 -> 66074 bytes V3/Content/Buttons/Button-07.png | Bin 0 -> 72189 bytes V3/Content/Buttons/Button-07_Pressed.png | Bin 0 -> 84575 bytes V3/Content/Content.mgcb | 1092 +++++++++++++++++ V3/Content/Effects/blood_hit_01.png | Bin 0 -> 109054 bytes V3/Content/Effects/blood_hit_02.png | Bin 0 -> 38081 bytes V3/Content/Effects/blood_hit_03.png | Bin 0 -> 41343 bytes V3/Content/Effects/blood_hit_04.png | Bin 0 -> 91450 bytes V3/Content/Effects/blood_hit_05.png | Bin 0 -> 71750 bytes V3/Content/Effects/blood_hit_06.png | Bin 0 -> 36776 bytes V3/Content/Effects/blood_hit_08.png | Bin 0 -> 115643 bytes V3/Content/Effects/explosion.png | Bin 0 -> 2623088 bytes V3/Content/Effects/particlefx_03.png | Bin 0 -> 972652 bytes V3/Content/Effects/particlefx_04.png | Bin 0 -> 821590 bytes V3/Content/Effects/particlefx_05.png | Bin 0 -> 544650 bytes V3/Content/Effects/quake.png | Bin 0 -> 122179 bytes V3/Content/Fonts/Blutschrift.ttf | Bin 0 -> 256596 bytes V3/Content/Fonts/DeathFont.spritefont | 50 + V3/Content/Fonts/DejaVuSans.ttf | Bin 0 -> 756072 bytes V3/Content/Fonts/MenuFont.spritefont | 50 + V3/Content/Fonts/Siegesschriftzug.ttf | Bin 0 -> 1081476 bytes V3/Content/Fonts/UnitFont.spritefont | 50 + V3/Content/Fonts/VictoryFont.spritefont | 50 + V3/Content/Fonts/grabstein.ttf | Bin 0 -> 21676 bytes V3/Content/Maps/map_grassland.tmx | 988 +++++++++++++++ V3/Content/Maps/techdemo.tmx | 1170 ++++++++++++++++++ V3/Content/Maps/work_in_progress.tmx | 1258 ++++++++++++++++++++ V3/Content/Menu/Titel.png | Bin 0 -> 91996 bytes V3/Content/Menu/arrow_white.png | Bin 0 -> 3981 bytes V3/Content/Menu/mainscreen.jpg | Bin 0 -> 3376885 bytes V3/Content/Sounds/Afraid_to_Go.mp3 | Bin 0 -> 6975318 bytes V3/Content/Sounds/Knight.wav | Bin 0 -> 1947210 bytes V3/Content/Sounds/Kosta_T_-_06.mp3 | Bin 0 -> 11340892 bytes .../Sounds/Monster_Gigante-Doberman-1334685792.wav | Bin 0 -> 1175132 bytes V3/Content/Sounds/Mummy_Zombie-SoundBible.wav | Bin 0 -> 357466 bytes V3/Content/Sounds/SkeletonHorse.wav | Bin 0 -> 2759074 bytes V3/Content/Sounds/explode.wav | Bin 0 -> 303992 bytes V3/Content/Sounds/explodemini.wav | Bin 0 -> 277340 bytes V3/Content/Sounds/explosion1.ogg | Bin 0 -> 37165 bytes V3/Content/Sounds/horse.wav | Bin 0 -> 14032 bytes V3/Content/Sounds/impactsplat01.ogg | Bin 0 -> 21825 bytes V3/Content/Sounds/punch.wav | Bin 0 -> 140058 bytes V3/Content/Sounds/walking.wav | Bin 0 -> 2102948 bytes V3/Content/Sounds/zonk2.wav | Bin 0 -> 95374 bytes V3/Content/Sources/Horse.blend | Bin 0 -> 11055184 bytes V3/Content/Sources/Skeleton.blend | Bin 0 -> 1101828 bytes V3/Content/Sources/SkeletonHorse.blend | Bin 0 -> 2900188 bytes V3/Content/Sources/SkeletonHorse.png | Bin 0 -> 1013788 bytes V3/Content/Sources/SkeletonRider.blend | Bin 0 -> 4551660 bytes V3/Content/Sources/SkeletonRider.png | Bin 0 -> 734006 bytes V3/Content/Sources/ZombieWithClub.png | Bin 0 -> 921761 bytes V3/Content/Sources/castle.xcf | Bin 0 -> 525634 bytes V3/Content/Sources/create_spritesheet.sh | 7 + V3/Content/Sources/fleischklops.blend | Bin 0 -> 2307520 bytes V3/Content/Sources/fleischklops.xcf | Bin 0 -> 1387154 bytes V3/Content/Sources/horse_paint.png | Bin 0 -> 898326 bytes V3/Content/Sources/horse_paint_sc.png | Bin 0 -> 1460647 bytes V3/Content/Sources/horse_tack.png | Bin 0 -> 879871 bytes V3/Content/Sources/houses_front.xcf | Bin 0 -> 221614 bytes V3/Content/Sources/houses_rear.xcf | Bin 0 -> 205943 bytes V3/Content/Sources/human_construction_set.xcf | Bin 0 -> 10007151 bytes .../Sources/human_construction_set_female.xcf | Bin 0 -> 6728872 bytes V3/Content/Sources/king.blend | Bin 0 -> 4472284 bytes V3/Content/Sources/king_head.png | Bin 0 -> 131639 bytes V3/Content/Sources/necromancer.xcf | Bin 0 -> 5307898 bytes V3/Content/Sources/pathfinder.xcf | Bin 0 -> 2470 bytes V3/Content/Sources/prince.blend | Bin 0 -> 3927028 bytes V3/Content/Sources/prince.xcf | Bin 0 -> 2523537 bytes V3/Content/Sources/selection.xcf | Bin 0 -> 151080 bytes V3/Content/Sources/skeleton_horse.png | Bin 0 -> 1083757 bytes V3/Content/Sources/the_triumph_of_death.jpg | Bin 0 -> 3376885 bytes V3/Content/Sources/zombie.blend | Bin 0 -> 1563140 bytes V3/Content/Sprites/WhiteRectangle.png | Bin 0 -> 67 bytes V3/Content/Sprites/arrows.png | Bin 0 -> 4218 bytes V3/Content/Sprites/buckler.png | Bin 0 -> 189331 bytes V3/Content/Sprites/buckler_female.png | Bin 0 -> 150081 bytes V3/Content/Sprites/chain.png | Bin 0 -> 680942 bytes V3/Content/Sprites/chain_female.png | Bin 0 -> 594899 bytes V3/Content/Sprites/cloth.png | Bin 0 -> 627879 bytes V3/Content/Sprites/cloth_female.png | Bin 0 -> 560029 bytes V3/Content/Sprites/cloud.png | Bin 0 -> 54576 bytes V3/Content/Sprites/ellipse.png | Bin 0 -> 10943 bytes V3/Content/Sprites/fleischklops.png | Bin 0 -> 2466843 bytes V3/Content/Sprites/fog.png | Bin 0 -> 44834 bytes V3/Content/Sprites/head.png | Bin 0 -> 105453 bytes V3/Content/Sprites/head_bald.png | Bin 0 -> 107161 bytes V3/Content/Sprites/head_chain.png | Bin 0 -> 145589 bytes V3/Content/Sprites/head_chain_female.png | Bin 0 -> 134925 bytes V3/Content/Sprites/head_female.png | Bin 0 -> 120410 bytes V3/Content/Sprites/head_plate.png | Bin 0 -> 158766 bytes V3/Content/Sprites/head_plate_female.png | Bin 0 -> 146096 bytes V3/Content/Sprites/king.png | Bin 0 -> 822995 bytes V3/Content/Sprites/longsword.png | Bin 0 -> 145022 bytes V3/Content/Sprites/longsword_female.png | Bin 0 -> 156551 bytes V3/Content/Sprites/necromancer.png | Bin 0 -> 705759 bytes V3/Content/Sprites/necromancer_female.png | Bin 0 -> 659280 bytes V3/Content/Sprites/nude.png | Bin 0 -> 632199 bytes V3/Content/Sprites/nude_female.png | Bin 0 -> 567054 bytes V3/Content/Sprites/plate.png | Bin 0 -> 702344 bytes V3/Content/Sprites/plate_female.png | Bin 0 -> 623813 bytes V3/Content/Sprites/prince.png | Bin 0 -> 855383 bytes V3/Content/Sprites/selection.png | Bin 0 -> 1327 bytes V3/Content/Sprites/shield.png | Bin 0 -> 253328 bytes V3/Content/Sprites/shield_female.png | Bin 0 -> 257298 bytes V3/Content/Sprites/shortsword.png | Bin 0 -> 91334 bytes V3/Content/Sprites/shortsword_female.png | Bin 0 -> 99034 bytes V3/Content/Sprites/skeleton.png | Bin 0 -> 950304 bytes V3/Content/Sprites/skeleton_archer.png | Bin 0 -> 1082133 bytes V3/Content/Sprites/skeleton_elite.png | Bin 0 -> 1191913 bytes V3/Content/Sprites/skeleton_horse.png | Bin 0 -> 1013788 bytes V3/Content/Sprites/skeleton_rider.png | Bin 0 -> 734006 bytes V3/Content/Sprites/staff.png | Bin 0 -> 324639 bytes V3/Content/Sprites/staff_female.png | Bin 0 -> 336664 bytes V3/Content/Sprites/zombie.png | Bin 0 -> 801160 bytes V3/Content/Sprites/zombie_club.png | Bin 0 -> 921761 bytes V3/Content/Textures/EmptyPixel.png | Bin 0 -> 169 bytes V3/Content/Textures/castle.png | Bin 0 -> 1668329 bytes V3/Content/Textures/grassland.png | Bin 0 -> 430934 bytes V3/Content/Textures/grassland_trees.png | Bin 0 -> 445999 bytes V3/Content/Textures/grassland_water.png | Bin 0 -> 254809 bytes V3/Content/Textures/houses_front.png | Bin 0 -> 287910 bytes V3/Content/Textures/houses_rear.png | Bin 0 -> 302161 bytes V3/Content/Textures/medieval_building_tiles.png | Bin 0 -> 515727 bytes V3/Content/Textures/pathfinder.png | Bin 0 -> 289 bytes V3/Data/DebugMode.cs | 21 + V3/Data/GameState.cs | 64 + V3/Data/IGameStateManager.cs | 20 + V3/Data/IOptionsManager.cs | 18 + V3/Data/IPathManager.cs | 30 + V3/Data/ISaveGame.cs | 25 + V3/Data/ISaveGameManager.cs | 25 + V3/Data/Internal/GameStateManager.cs | 81 ++ V3/Data/Internal/OptionsManager.cs | 65 + V3/Data/Internal/PathManager.cs | 51 + V3/Data/Internal/SaveGame.cs | 65 + V3/Data/Internal/SaveGameManager.cs | 88 ++ V3/Data/Options.cs | 105 ++ V3/Effects/AbstractEffect.cs | 74 ++ V3/Effects/BloodBang.cs | 8 + V3/Effects/BloodExplosion.cs | 11 + V3/Effects/BloodFountain.cs | 11 + V3/Effects/EffectsManager.cs | 54 + V3/Effects/Explosion.cs | 14 + V3/Effects/HorseEffect.cs | 11 + V3/Effects/IEffect.cs | 44 + V3/Effects/IEffectsManager.cs | 31 + V3/Effects/Quake.cs | 11 + V3/Effects/SmokeBig.cs | 10 + V3/Effects/SmokeMedium.cs | 13 + V3/Effects/SmokeSmall.cs | 10 + V3/Ellipse.cs | 31 + V3/Faction.cs | 7 + V3/Icon.ico | Bin 0 -> 32038 bytes V3/Input/IInputManager.cs | 34 + V3/Input/IKeyEvent.cs | 20 + V3/Input/IMouseEvent.cs | 34 + V3/Input/IMouseEventHandler.cs | 14 + V3/Input/Internal/InputManager.cs | 141 +++ V3/Input/Internal/KeyEvent.cs | 32 + V3/Input/Internal/MouseEvent.cs | 57 + V3/Input/MouseButton.cs | 9 + V3/Map/AbstractLayer.cs | 259 ++++ V3/Map/Area.cs | 119 ++ V3/Map/Constants.cs | 12 + V3/Map/FloorLayer.cs | 21 + V3/Map/FogOfWar.cs | 107 ++ V3/Map/IMapManager.cs | 88 ++ V3/Map/MapManager.cs | 97 ++ V3/Map/ObjectLayer.cs | 16 + V3/Map/Pathfinder.cs | 455 +++++++ V3/Map/PathfindingGrid.cs | 125 ++ V3/Map/SearchNode.cs | 31 + V3/Map/TiledParser.cs | 256 ++++ V3/Map/Tileset.cs | 89 ++ V3/Node.cs | 467 ++++++++ V3/Objects/AbstractBuilding.cs | 110 ++ V3/Objects/AbstractCreature.cs | 911 ++++++++++++++ V3/Objects/Arrow.cs | 109 ++ V3/Objects/BuildingState.cs | 8 + V3/Objects/Castle.cs | 15 + V3/Objects/CreatureFactory.cs | 127 ++ V3/Objects/FemalePeasant.cs | 50 + V3/Objects/Forge.cs | 19 + V3/Objects/IBasicCreatureFactory.cs | 28 + V3/Objects/IBuilding.cs | 20 + V3/Objects/ICreature.cs | 120 ++ V3/Objects/IGameObject.cs | 43 + V3/Objects/IObjectsManager.cs | 131 ++ V3/Objects/IdGenerator.cs | 59 + V3/Objects/King.cs | 33 + V3/Objects/KingsGuard.cs | 62 + V3/Objects/Knight.cs | 65 + V3/Objects/MalePeasant.cs | 49 + V3/Objects/Meatball.cs | 36 + V3/Objects/Movement.cs | 20 + V3/Objects/Movement/CountStepsMovement.cs | 16 + V3/Objects/Movement/IMovable.cs | 43 + V3/Objects/Movement/PlayerMovement.cs | 155 +++ V3/Objects/Necromancer.cs | 61 + V3/Objects/ObjectsManager.cs | 314 +++++ V3/Objects/Prince.cs | 33 + V3/Objects/Selection.cs | 483 ++++++++ V3/Objects/Skeleton.cs | 65 + V3/Objects/SkeletonElite.cs | 19 + V3/Objects/SkeletonHorse.cs | 87 ++ V3/Objects/Sprite/AbstractSpriteCreature.cs | 201 ++++ V3/Objects/Sprite/ArrowSprite.cs | 42 + V3/Objects/Sprite/BucklerFemaleSprite.cs | 7 + V3/Objects/Sprite/BucklerSprite.cs | 7 + V3/Objects/Sprite/ChainFemaleSprite.cs | 7 + V3/Objects/Sprite/ChainSprite.cs | 7 + V3/Objects/Sprite/ClothFemaleSprite.cs | 7 + V3/Objects/Sprite/ClothSprite.cs | 7 + V3/Objects/Sprite/EquipmentType.cs | 10 + V3/Objects/Sprite/HeadBaldSprite.cs | 10 + V3/Objects/Sprite/HeadChainFemaleSprite.cs | 7 + V3/Objects/Sprite/HeadChainSprite.cs | 7 + V3/Objects/Sprite/HeadFemaleSprite.cs | 7 + V3/Objects/Sprite/HeadPlateFemaleSprite.cs | 7 + V3/Objects/Sprite/HeadPlateSprite.cs | 7 + V3/Objects/Sprite/HeadSprite.cs | 7 + V3/Objects/Sprite/ISpriteCreature.cs | 53 + V3/Objects/Sprite/KingSprite.cs | 7 + V3/Objects/Sprite/LongswordFemaleSprite.cs | 7 + V3/Objects/Sprite/LongswordSprite.cs | 7 + V3/Objects/Sprite/MeatballSprite.cs | 11 + V3/Objects/Sprite/NecromancerFemaleSprite.cs | 7 + V3/Objects/Sprite/NecromancerSprite.cs | 7 + V3/Objects/Sprite/NudeFemaleSprite.cs | 7 + V3/Objects/Sprite/NudeSprite.cs | 7 + V3/Objects/Sprite/PlateFemaleSprite.cs | 7 + V3/Objects/Sprite/PlateSprite.cs | 7 + V3/Objects/Sprite/PrinceSprite.cs | 7 + V3/Objects/Sprite/ShieldFemaleSprite.cs | 7 + V3/Objects/Sprite/ShieldSprite.cs | 7 + V3/Objects/Sprite/ShortswordFemaleSprite.cs | 7 + V3/Objects/Sprite/ShortswordSprite.cs | 7 + V3/Objects/Sprite/SkeletonArcherSprite.cs | 10 + V3/Objects/Sprite/SkeletonEliteSprite.cs | 9 + V3/Objects/Sprite/SkeletonHorseSprite.cs | 7 + V3/Objects/Sprite/SkeletonRiderSprite.cs | 10 + V3/Objects/Sprite/SkeletonSprite.cs | 9 + V3/Objects/Sprite/StaffFemaleSprite.cs | 7 + V3/Objects/Sprite/StaffSprite.cs | 7 + V3/Objects/Sprite/ZombieSprite.cs | 11 + V3/Objects/Sprite/ZombieWithClubSprite.cs | 11 + V3/Objects/TextureObject.cs | 76 ++ V3/Objects/Transformation.cs | 102 ++ V3/Objects/Woodhouse.cs | 16 + V3/Objects/Zombie.cs | 45 + V3/OpenTK.dll.config | 25 + V3/Program.cs | 20 + V3/Properties/AssemblyInfo.cs | 35 + V3/Quadtree.cs | 87 ++ V3/Screens/AbstractScreen.cs | 57 + V3/Screens/AchievementsScreen.cs | 221 ++++ V3/Screens/DeathScreen.cs | 140 +++ V3/Screens/DebugScreen.cs | 92 ++ V3/Screens/FpsCounter.cs | 46 + V3/Screens/GameScreen.cs | 306 +++++ V3/Screens/HudScreen.cs | 349 ++++++ V3/Screens/IDrawable.cs | 19 + V3/Screens/IScreen.cs | 39 + V3/Screens/IScreenFactory.cs | 27 + V3/Screens/IScreenManager.cs | 35 + V3/Screens/IUpdatable.cs | 16 + V3/Screens/LoadScreen.cs | 124 ++ V3/Screens/MainScreen.cs | 195 +++ V3/Screens/MenuActions.cs | 208 ++++ V3/Screens/OptionsScreen.cs | 197 +++ V3/Screens/PauseScreen.cs | 140 +++ V3/Screens/ScreenManager.cs | 164 +++ V3/Screens/StatisticsScreen.cs | 186 +++ V3/Screens/TechdemoScreen.cs | 325 +++++ V3/Screens/VictoryScreen.cs | 76 ++ V3/UpdatesPerSecond.cs | 55 + V3/V3.csproj | 498 ++++++++ V3/V3Game.cs | 78 ++ V3/Widgets/AbstractMenu.cs | 96 ++ V3/Widgets/AbstractTextWidget.cs | 113 ++ V3/Widgets/AchievementBox.cs | 91 ++ V3/Widgets/Button.cs | 111 ++ V3/Widgets/EmptyWidget.cs | 41 + V3/Widgets/FormMenu.cs | 75 ++ V3/Widgets/HorizontalOrientation.cs | 9 + V3/Widgets/IBasicWidgetFactory.cs | 38 + V3/Widgets/IClickable.cs | 14 + V3/Widgets/IImageWidget.cs | 15 + V3/Widgets/IMenu.cs | 33 + V3/Widgets/IMenuFactory.cs | 9 + V3/Widgets/ISelectable.cs | 27 + V3/Widgets/ITextWidget.cs | 43 + V3/Widgets/IWidget.cs | 34 + V3/Widgets/Label.cs | 14 + V3/Widgets/SelectButton.cs | 108 ++ V3/Widgets/VerticalMenu.cs | 42 + V3/Widgets/WidgetFactory.cs | 78 ++ V3/packages.config | 6 + 332 files changed, 18155 insertions(+) create mode 100644 V3/AI/ActionState.cs create mode 100644 V3/AI/AiState.cs create mode 100644 V3/AI/IAction.cs create mode 100644 V3/AI/IAiPlayer.cs create mode 100644 V3/AI/IStrategy.cs create mode 100644 V3/AI/IWorldView.cs create mode 100644 V3/AI/Internal/AbstractAction.cs create mode 100644 V3/AI/Internal/AiPlayer.cs create mode 100644 V3/AI/Internal/AttackStrategy.cs create mode 100644 V3/AI/Internal/IActionFactory.cs create mode 100644 V3/AI/Internal/MoveAction.cs create mode 100644 V3/AI/Internal/SpawnAction.cs create mode 100644 V3/AI/Internal/WorldView.cs create mode 100644 V3/AchievementsAndStatistics.cs create mode 100644 V3/Bindings.cs create mode 100644 V3/CONTROLS.md create mode 100644 V3/CREDITS.md create mode 100644 V3/Camera/CameraCentered.cs create mode 100644 V3/Camera/CameraManager.cs create mode 100644 V3/Camera/CameraScrolling.cs create mode 100644 V3/Camera/CameraType.cs create mode 100644 V3/Camera/ICamera.cs create mode 100644 V3/ClassDiagram1.cd create mode 100644 V3/Content/Buttons/Button-01.png create mode 100644 V3/Content/Buttons/Button-01_Pressed.png create mode 100644 V3/Content/Buttons/Button-02.png create mode 100644 V3/Content/Buttons/Button-02_Pressed.png create mode 100644 V3/Content/Buttons/Button-03.png create mode 100644 V3/Content/Buttons/Button-03_Pressed.png create mode 100644 V3/Content/Buttons/Button-04.png create mode 100644 V3/Content/Buttons/Button-04_Pressed.png create mode 100644 V3/Content/Buttons/Button-05.png create mode 100644 V3/Content/Buttons/Button-05_Pressed.png create mode 100644 V3/Content/Buttons/Button-06.png create mode 100644 V3/Content/Buttons/Button-06_Pressed.png create mode 100644 V3/Content/Buttons/Button-07.png create mode 100644 V3/Content/Buttons/Button-07_Pressed.png create mode 100644 V3/Content/Content.mgcb create mode 100644 V3/Content/Effects/blood_hit_01.png create mode 100644 V3/Content/Effects/blood_hit_02.png create mode 100644 V3/Content/Effects/blood_hit_03.png create mode 100644 V3/Content/Effects/blood_hit_04.png create mode 100644 V3/Content/Effects/blood_hit_05.png create mode 100644 V3/Content/Effects/blood_hit_06.png create mode 100644 V3/Content/Effects/blood_hit_08.png create mode 100644 V3/Content/Effects/explosion.png create mode 100644 V3/Content/Effects/particlefx_03.png create mode 100644 V3/Content/Effects/particlefx_04.png create mode 100644 V3/Content/Effects/particlefx_05.png create mode 100644 V3/Content/Effects/quake.png create mode 100644 V3/Content/Fonts/Blutschrift.ttf create mode 100644 V3/Content/Fonts/DeathFont.spritefont create mode 100644 V3/Content/Fonts/DejaVuSans.ttf create mode 100644 V3/Content/Fonts/MenuFont.spritefont create mode 100644 V3/Content/Fonts/Siegesschriftzug.ttf create mode 100644 V3/Content/Fonts/UnitFont.spritefont create mode 100644 V3/Content/Fonts/VictoryFont.spritefont create mode 100644 V3/Content/Fonts/grabstein.ttf create mode 100644 V3/Content/Maps/map_grassland.tmx create mode 100644 V3/Content/Maps/techdemo.tmx create mode 100644 V3/Content/Maps/work_in_progress.tmx create mode 100644 V3/Content/Menu/Titel.png create mode 100644 V3/Content/Menu/arrow_white.png create mode 100644 V3/Content/Menu/mainscreen.jpg create mode 100644 V3/Content/Sounds/Afraid_to_Go.mp3 create mode 100644 V3/Content/Sounds/Knight.wav create mode 100644 V3/Content/Sounds/Kosta_T_-_06.mp3 create mode 100644 V3/Content/Sounds/Monster_Gigante-Doberman-1334685792.wav create mode 100644 V3/Content/Sounds/Mummy_Zombie-SoundBible.wav create mode 100644 V3/Content/Sounds/SkeletonHorse.wav create mode 100644 V3/Content/Sounds/explode.wav create mode 100644 V3/Content/Sounds/explodemini.wav create mode 100644 V3/Content/Sounds/explosion1.ogg create mode 100644 V3/Content/Sounds/horse.wav create mode 100644 V3/Content/Sounds/impactsplat01.ogg create mode 100644 V3/Content/Sounds/punch.wav create mode 100644 V3/Content/Sounds/walking.wav create mode 100644 V3/Content/Sounds/zonk2.wav create mode 100644 V3/Content/Sources/Horse.blend create mode 100644 V3/Content/Sources/Skeleton.blend create mode 100644 V3/Content/Sources/SkeletonHorse.blend create mode 100644 V3/Content/Sources/SkeletonHorse.png create mode 100644 V3/Content/Sources/SkeletonRider.blend create mode 100644 V3/Content/Sources/SkeletonRider.png create mode 100644 V3/Content/Sources/ZombieWithClub.png create mode 100644 V3/Content/Sources/castle.xcf create mode 100644 V3/Content/Sources/create_spritesheet.sh create mode 100644 V3/Content/Sources/fleischklops.blend create mode 100644 V3/Content/Sources/fleischklops.xcf create mode 100644 V3/Content/Sources/horse_paint.png create mode 100644 V3/Content/Sources/horse_paint_sc.png create mode 100644 V3/Content/Sources/horse_tack.png create mode 100644 V3/Content/Sources/houses_front.xcf create mode 100644 V3/Content/Sources/houses_rear.xcf create mode 100644 V3/Content/Sources/human_construction_set.xcf create mode 100644 V3/Content/Sources/human_construction_set_female.xcf create mode 100644 V3/Content/Sources/king.blend create mode 100644 V3/Content/Sources/king_head.png create mode 100644 V3/Content/Sources/necromancer.xcf create mode 100644 V3/Content/Sources/pathfinder.xcf create mode 100644 V3/Content/Sources/prince.blend create mode 100644 V3/Content/Sources/prince.xcf create mode 100644 V3/Content/Sources/selection.xcf create mode 100644 V3/Content/Sources/skeleton_horse.png create mode 100644 V3/Content/Sources/the_triumph_of_death.jpg create mode 100644 V3/Content/Sources/zombie.blend create mode 100644 V3/Content/Sprites/WhiteRectangle.png create mode 100644 V3/Content/Sprites/arrows.png create mode 100644 V3/Content/Sprites/buckler.png create mode 100644 V3/Content/Sprites/buckler_female.png create mode 100644 V3/Content/Sprites/chain.png create mode 100644 V3/Content/Sprites/chain_female.png create mode 100644 V3/Content/Sprites/cloth.png create mode 100644 V3/Content/Sprites/cloth_female.png create mode 100644 V3/Content/Sprites/cloud.png create mode 100644 V3/Content/Sprites/ellipse.png create mode 100644 V3/Content/Sprites/fleischklops.png create mode 100644 V3/Content/Sprites/fog.png create mode 100644 V3/Content/Sprites/head.png create mode 100644 V3/Content/Sprites/head_bald.png create mode 100644 V3/Content/Sprites/head_chain.png create mode 100644 V3/Content/Sprites/head_chain_female.png create mode 100644 V3/Content/Sprites/head_female.png create mode 100644 V3/Content/Sprites/head_plate.png create mode 100644 V3/Content/Sprites/head_plate_female.png create mode 100644 V3/Content/Sprites/king.png create mode 100644 V3/Content/Sprites/longsword.png create mode 100644 V3/Content/Sprites/longsword_female.png create mode 100644 V3/Content/Sprites/necromancer.png create mode 100644 V3/Content/Sprites/necromancer_female.png create mode 100644 V3/Content/Sprites/nude.png create mode 100644 V3/Content/Sprites/nude_female.png create mode 100644 V3/Content/Sprites/plate.png create mode 100644 V3/Content/Sprites/plate_female.png create mode 100644 V3/Content/Sprites/prince.png create mode 100644 V3/Content/Sprites/selection.png create mode 100644 V3/Content/Sprites/shield.png create mode 100644 V3/Content/Sprites/shield_female.png create mode 100644 V3/Content/Sprites/shortsword.png create mode 100644 V3/Content/Sprites/shortsword_female.png create mode 100644 V3/Content/Sprites/skeleton.png create mode 100644 V3/Content/Sprites/skeleton_archer.png create mode 100644 V3/Content/Sprites/skeleton_elite.png create mode 100644 V3/Content/Sprites/skeleton_horse.png create mode 100644 V3/Content/Sprites/skeleton_rider.png create mode 100644 V3/Content/Sprites/staff.png create mode 100644 V3/Content/Sprites/staff_female.png create mode 100644 V3/Content/Sprites/zombie.png create mode 100644 V3/Content/Sprites/zombie_club.png create mode 100644 V3/Content/Textures/EmptyPixel.png create mode 100644 V3/Content/Textures/castle.png create mode 100644 V3/Content/Textures/grassland.png create mode 100644 V3/Content/Textures/grassland_trees.png create mode 100644 V3/Content/Textures/grassland_water.png create mode 100644 V3/Content/Textures/houses_front.png create mode 100644 V3/Content/Textures/houses_rear.png create mode 100644 V3/Content/Textures/medieval_building_tiles.png create mode 100644 V3/Content/Textures/pathfinder.png create mode 100644 V3/Data/DebugMode.cs create mode 100644 V3/Data/GameState.cs create mode 100644 V3/Data/IGameStateManager.cs create mode 100644 V3/Data/IOptionsManager.cs create mode 100644 V3/Data/IPathManager.cs create mode 100644 V3/Data/ISaveGame.cs create mode 100644 V3/Data/ISaveGameManager.cs create mode 100644 V3/Data/Internal/GameStateManager.cs create mode 100644 V3/Data/Internal/OptionsManager.cs create mode 100644 V3/Data/Internal/PathManager.cs create mode 100644 V3/Data/Internal/SaveGame.cs create mode 100644 V3/Data/Internal/SaveGameManager.cs create mode 100644 V3/Data/Options.cs create mode 100644 V3/Effects/AbstractEffect.cs create mode 100644 V3/Effects/BloodBang.cs create mode 100644 V3/Effects/BloodExplosion.cs create mode 100644 V3/Effects/BloodFountain.cs create mode 100644 V3/Effects/EffectsManager.cs create mode 100644 V3/Effects/Explosion.cs create mode 100644 V3/Effects/HorseEffect.cs create mode 100644 V3/Effects/IEffect.cs create mode 100644 V3/Effects/IEffectsManager.cs create mode 100644 V3/Effects/Quake.cs create mode 100644 V3/Effects/SmokeBig.cs create mode 100644 V3/Effects/SmokeMedium.cs create mode 100644 V3/Effects/SmokeSmall.cs create mode 100644 V3/Ellipse.cs create mode 100644 V3/Faction.cs create mode 100644 V3/Icon.ico create mode 100644 V3/Input/IInputManager.cs create mode 100644 V3/Input/IKeyEvent.cs create mode 100644 V3/Input/IMouseEvent.cs create mode 100644 V3/Input/IMouseEventHandler.cs create mode 100644 V3/Input/Internal/InputManager.cs create mode 100644 V3/Input/Internal/KeyEvent.cs create mode 100644 V3/Input/Internal/MouseEvent.cs create mode 100644 V3/Input/MouseButton.cs create mode 100644 V3/Map/AbstractLayer.cs create mode 100644 V3/Map/Area.cs create mode 100644 V3/Map/Constants.cs create mode 100644 V3/Map/FloorLayer.cs create mode 100644 V3/Map/FogOfWar.cs create mode 100644 V3/Map/IMapManager.cs create mode 100644 V3/Map/MapManager.cs create mode 100644 V3/Map/ObjectLayer.cs create mode 100644 V3/Map/Pathfinder.cs create mode 100644 V3/Map/PathfindingGrid.cs create mode 100644 V3/Map/SearchNode.cs create mode 100644 V3/Map/TiledParser.cs create mode 100644 V3/Map/Tileset.cs create mode 100644 V3/Node.cs create mode 100644 V3/Objects/AbstractBuilding.cs create mode 100644 V3/Objects/AbstractCreature.cs create mode 100644 V3/Objects/Arrow.cs create mode 100644 V3/Objects/BuildingState.cs create mode 100644 V3/Objects/Castle.cs create mode 100644 V3/Objects/CreatureFactory.cs create mode 100644 V3/Objects/FemalePeasant.cs create mode 100644 V3/Objects/Forge.cs create mode 100644 V3/Objects/IBasicCreatureFactory.cs create mode 100644 V3/Objects/IBuilding.cs create mode 100644 V3/Objects/ICreature.cs create mode 100644 V3/Objects/IGameObject.cs create mode 100644 V3/Objects/IObjectsManager.cs create mode 100644 V3/Objects/IdGenerator.cs create mode 100644 V3/Objects/King.cs create mode 100644 V3/Objects/KingsGuard.cs create mode 100644 V3/Objects/Knight.cs create mode 100644 V3/Objects/MalePeasant.cs create mode 100644 V3/Objects/Meatball.cs create mode 100644 V3/Objects/Movement.cs create mode 100644 V3/Objects/Movement/CountStepsMovement.cs create mode 100644 V3/Objects/Movement/IMovable.cs create mode 100644 V3/Objects/Movement/PlayerMovement.cs create mode 100644 V3/Objects/Necromancer.cs create mode 100644 V3/Objects/ObjectsManager.cs create mode 100644 V3/Objects/Prince.cs create mode 100644 V3/Objects/Selection.cs create mode 100644 V3/Objects/Skeleton.cs create mode 100644 V3/Objects/SkeletonElite.cs create mode 100644 V3/Objects/SkeletonHorse.cs create mode 100644 V3/Objects/Sprite/AbstractSpriteCreature.cs create mode 100644 V3/Objects/Sprite/ArrowSprite.cs create mode 100644 V3/Objects/Sprite/BucklerFemaleSprite.cs create mode 100644 V3/Objects/Sprite/BucklerSprite.cs create mode 100644 V3/Objects/Sprite/ChainFemaleSprite.cs create mode 100644 V3/Objects/Sprite/ChainSprite.cs create mode 100644 V3/Objects/Sprite/ClothFemaleSprite.cs create mode 100644 V3/Objects/Sprite/ClothSprite.cs create mode 100644 V3/Objects/Sprite/EquipmentType.cs create mode 100644 V3/Objects/Sprite/HeadBaldSprite.cs create mode 100644 V3/Objects/Sprite/HeadChainFemaleSprite.cs create mode 100644 V3/Objects/Sprite/HeadChainSprite.cs create mode 100644 V3/Objects/Sprite/HeadFemaleSprite.cs create mode 100644 V3/Objects/Sprite/HeadPlateFemaleSprite.cs create mode 100644 V3/Objects/Sprite/HeadPlateSprite.cs create mode 100644 V3/Objects/Sprite/HeadSprite.cs create mode 100644 V3/Objects/Sprite/ISpriteCreature.cs create mode 100644 V3/Objects/Sprite/KingSprite.cs create mode 100644 V3/Objects/Sprite/LongswordFemaleSprite.cs create mode 100644 V3/Objects/Sprite/LongswordSprite.cs create mode 100644 V3/Objects/Sprite/MeatballSprite.cs create mode 100644 V3/Objects/Sprite/NecromancerFemaleSprite.cs create mode 100644 V3/Objects/Sprite/NecromancerSprite.cs create mode 100644 V3/Objects/Sprite/NudeFemaleSprite.cs create mode 100644 V3/Objects/Sprite/NudeSprite.cs create mode 100644 V3/Objects/Sprite/PlateFemaleSprite.cs create mode 100644 V3/Objects/Sprite/PlateSprite.cs create mode 100644 V3/Objects/Sprite/PrinceSprite.cs create mode 100644 V3/Objects/Sprite/ShieldFemaleSprite.cs create mode 100644 V3/Objects/Sprite/ShieldSprite.cs create mode 100644 V3/Objects/Sprite/ShortswordFemaleSprite.cs create mode 100644 V3/Objects/Sprite/ShortswordSprite.cs create mode 100644 V3/Objects/Sprite/SkeletonArcherSprite.cs create mode 100644 V3/Objects/Sprite/SkeletonEliteSprite.cs create mode 100644 V3/Objects/Sprite/SkeletonHorseSprite.cs create mode 100644 V3/Objects/Sprite/SkeletonRiderSprite.cs create mode 100644 V3/Objects/Sprite/SkeletonSprite.cs create mode 100644 V3/Objects/Sprite/StaffFemaleSprite.cs create mode 100644 V3/Objects/Sprite/StaffSprite.cs create mode 100644 V3/Objects/Sprite/ZombieSprite.cs create mode 100644 V3/Objects/Sprite/ZombieWithClubSprite.cs create mode 100644 V3/Objects/TextureObject.cs create mode 100644 V3/Objects/Transformation.cs create mode 100644 V3/Objects/Woodhouse.cs create mode 100644 V3/Objects/Zombie.cs create mode 100644 V3/OpenTK.dll.config create mode 100644 V3/Program.cs create mode 100644 V3/Properties/AssemblyInfo.cs create mode 100644 V3/Quadtree.cs create mode 100644 V3/Screens/AbstractScreen.cs create mode 100644 V3/Screens/AchievementsScreen.cs create mode 100644 V3/Screens/DeathScreen.cs create mode 100644 V3/Screens/DebugScreen.cs create mode 100644 V3/Screens/FpsCounter.cs create mode 100644 V3/Screens/GameScreen.cs create mode 100644 V3/Screens/HudScreen.cs create mode 100644 V3/Screens/IDrawable.cs create mode 100644 V3/Screens/IScreen.cs create mode 100644 V3/Screens/IScreenFactory.cs create mode 100644 V3/Screens/IScreenManager.cs create mode 100644 V3/Screens/IUpdatable.cs create mode 100644 V3/Screens/LoadScreen.cs create mode 100644 V3/Screens/MainScreen.cs create mode 100644 V3/Screens/MenuActions.cs create mode 100644 V3/Screens/OptionsScreen.cs create mode 100644 V3/Screens/PauseScreen.cs create mode 100644 V3/Screens/ScreenManager.cs create mode 100644 V3/Screens/StatisticsScreen.cs create mode 100644 V3/Screens/TechdemoScreen.cs create mode 100644 V3/Screens/VictoryScreen.cs create mode 100644 V3/UpdatesPerSecond.cs create mode 100644 V3/V3.csproj create mode 100644 V3/V3Game.cs create mode 100644 V3/Widgets/AbstractMenu.cs create mode 100644 V3/Widgets/AbstractTextWidget.cs create mode 100644 V3/Widgets/AchievementBox.cs create mode 100644 V3/Widgets/Button.cs create mode 100644 V3/Widgets/EmptyWidget.cs create mode 100644 V3/Widgets/FormMenu.cs create mode 100644 V3/Widgets/HorizontalOrientation.cs create mode 100644 V3/Widgets/IBasicWidgetFactory.cs create mode 100644 V3/Widgets/IClickable.cs create mode 100644 V3/Widgets/IImageWidget.cs create mode 100644 V3/Widgets/IMenu.cs create mode 100644 V3/Widgets/IMenuFactory.cs create mode 100644 V3/Widgets/ISelectable.cs create mode 100644 V3/Widgets/ITextWidget.cs create mode 100644 V3/Widgets/IWidget.cs create mode 100644 V3/Widgets/Label.cs create mode 100644 V3/Widgets/SelectButton.cs create mode 100644 V3/Widgets/VerticalMenu.cs create mode 100644 V3/Widgets/WidgetFactory.cs create mode 100644 V3/packages.config (limited to 'V3') diff --git a/V3/AI/ActionState.cs b/V3/AI/ActionState.cs new file mode 100644 index 0000000..18996c8 --- /dev/null +++ b/V3/AI/ActionState.cs @@ -0,0 +1,25 @@ +namespace V3.AI +{ + /// + /// The state of an action taken by the computer player. + /// + public enum ActionState + { + /// + /// The action is waiting to be executed. + /// + Waiting, + /// + /// The action is currently being executed. + /// + Executing, + /// + /// The action has been done successfully. + /// + Done, + /// + /// The action failed. + /// + Failed + } +} diff --git a/V3/AI/AiState.cs b/V3/AI/AiState.cs new file mode 100644 index 0000000..1bc0ab0 --- /dev/null +++ b/V3/AI/AiState.cs @@ -0,0 +1,27 @@ +namespace V3.AI +{ + /// + /// An action state for the AI player that is part of a strategy. A state + /// defines the specific actions to take (for example, defend peasants, or + /// attack enemy creatures). + /// + public enum AiState + { + /// + /// Waiting for the player actions. + /// + Idle, + /// + /// Defend peasants so that they don't become zombies. + /// + DefendPeasants, + /// + /// Attack enemy creatures. + /// + AttackCreatures, + /// + /// Attack the necromancer directly. + /// + AttackNecromancer + } +} diff --git a/V3/AI/IAction.cs b/V3/AI/IAction.cs new file mode 100644 index 0000000..b68355f --- /dev/null +++ b/V3/AI/IAction.cs @@ -0,0 +1,24 @@ +namespace V3.AI +{ + /// + /// An action that can be taken by the computer player. + /// + public interface IAction + { + /// + /// The current state of the action. + /// + ActionState State { get; } + + /// + /// Start the execution of the action. + /// + void Start(); + + /// + /// Update the execution state. This method should be repateatingly + /// called as long as State is Executing. + /// + void Update(); + } +} diff --git a/V3/AI/IAiPlayer.cs b/V3/AI/IAiPlayer.cs new file mode 100644 index 0000000..7f5f81b --- /dev/null +++ b/V3/AI/IAiPlayer.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; + +namespace V3.AI +{ + /// + /// A computer player that takes actions according to a specified strategy. + /// + public interface IAiPlayer + { + /// + /// The current world view of the player. It stores the knowledge of + /// the computer player based on the previous percepts. + /// + IWorldView WorldView { get; } + /// + /// The strategy of the player. The strategy is a state machine that + /// defines the current state. + /// + IStrategy Strategy { get; } + /// + /// The current state of the player. The state is one step of the + /// strategy, and defines the specific actions to take. + /// + AiState State { get; set; } + /// + /// The actions that the player wants to be executed. Updated by + /// Act. + /// + IList Actions { get; } + + /// + /// Executes one update cycle -- perception, acting and the execution + /// of actions. + /// + /// the time since the last update + void Update(GameTime gameTime); + + /// + /// Update the AI's view of the game world. + /// + void Percept(); + + /// + /// Take actions based on the previous percepts, the current strategy + /// and state. Updates the list of actions stored in Actions. These + /// should be executed by the caller. + /// + void Act(); + } +} diff --git a/V3/AI/IStrategy.cs b/V3/AI/IStrategy.cs new file mode 100644 index 0000000..4bfb99c --- /dev/null +++ b/V3/AI/IStrategy.cs @@ -0,0 +1,17 @@ +namespace V3.AI +{ + /// + /// A strategy for the computer player. A strategy is a finite state + /// machine. + /// + public interface IStrategy + { + /// + /// Updates the current state according to the game situtation. + /// + /// the current state + /// the current view of the game world + /// the next state indicated by this strategy + AiState Update(AiState state, IWorldView worldView); + } +} diff --git a/V3/AI/IWorldView.cs b/V3/AI/IWorldView.cs new file mode 100644 index 0000000..b47322f --- /dev/null +++ b/V3/AI/IWorldView.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using V3.Objects; + +namespace V3.AI +{ + /// + /// Stores the knowledge of the computer player about the game world, and + /// is used for the evaluation of the strategy. It is also used to decide + /// which actions to take based on the current state. + /// + public interface IWorldView + { + int EnemyCount { get; set; } + int InitialPlebsCount { get; set; } + int PlebsCount { get; set; } + float NecromancerHealth { get; set; } + List IdlingKnights { get; } + List Targets { get; } + List Plebs { get; } + } +} diff --git a/V3/AI/Internal/AbstractAction.cs b/V3/AI/Internal/AbstractAction.cs new file mode 100644 index 0000000..1b5f73e --- /dev/null +++ b/V3/AI/Internal/AbstractAction.cs @@ -0,0 +1,38 @@ +namespace V3.AI.Internal +{ + /// + /// Abstract implementation of IAction. + /// + public abstract class AbstractAction : IAction + { + /// + /// The current state of the action. + /// + public ActionState State { get; private set; } = ActionState.Waiting; + + /// + /// Start the execution of the action. + /// + public virtual void Start() + { + State = ActionState.Executing; + } + + /// + /// Update the execution state. This method should be repateatingly + /// called as long as State is Executing. + /// + public virtual void Update() + { + if (State != ActionState.Executing) + return; + State = GetNextState(); + } + + /// + /// Returns the next state of this action. It is guaranteed that the + /// current state is Executing. + /// + protected abstract ActionState GetNextState(); + } +} diff --git a/V3/AI/Internal/AiPlayer.cs b/V3/AI/Internal/AiPlayer.cs new file mode 100644 index 0000000..6040348 --- /dev/null +++ b/V3/AI/Internal/AiPlayer.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.AI.Internal +{ + /// + /// Default implementation of IAiPlayer. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public class AiPlayer : IAiPlayer + { + /// + /// The current world view of the player. It stores the knowledge of + /// the computer player based on the previous percepts. + /// + public IWorldView WorldView { get; } = new WorldView(); + /// + /// The strategy of the player. The strategy is a state machine that + /// defines the current state. + /// + public IStrategy Strategy { get; } = new AttackStrategy(); + /// + /// The current state of the player. The state is one step of the + /// strategy, and defines the specific actions to take. + /// + public AiState State { get; set; } = AiState.Idle; + /// + /// The actions that the player wants to be executed. Updated by + /// Act. + /// + public IList Actions { get; } = new List(); + + private readonly IActionFactory mActionFactory; + private readonly IBasicCreatureFactory mCreatureFactory; + private readonly IObjectsManager mObjectsManager; + private readonly UpdatesPerSecond mUpS = new UpdatesPerSecond(1); + private readonly Random mRandom = new Random(); + private TimeSpan mTimeSpan = TimeSpan.Zero; + private TimeSpan mTimeSpanSpawn = TimeSpan.Zero; + private int mMaxWaitBaseMs = (int) TimeSpan.FromSeconds(20).TotalMilliseconds; + private int mMaxWaitAddMs = (int) TimeSpan.FromSeconds(60).TotalMilliseconds; + + /// + /// Creates a new AI player. + /// + public AiPlayer(IActionFactory actionFactory, IBasicCreatureFactory creatureFactory, + IObjectsManager objectsManager) + { + mActionFactory = actionFactory; + mCreatureFactory = creatureFactory; + mObjectsManager = objectsManager; + } + + /// + /// Executes one update cycle -- perception, acting and the execution + /// of actions. + /// + /// the time since the last update + public void Update(GameTime gameTime) + { + mTimeSpan += gameTime.ElapsedGameTime; + if (!mUpS.IsItTime(gameTime)) + return; + Percept(); + Act(); + foreach (var action in Actions) + { + if (action.State == ActionState.Waiting) + action.Start(); + action.Update(); + } + } + + /// + /// Update the AI's view of the game world. + /// + public void Percept() + { + WorldView.EnemyCount = 0; + WorldView.PlebsCount = 0; + WorldView.NecromancerHealth = 0; + WorldView.IdlingKnights.Clear(); + WorldView.Targets.Clear(); + WorldView.Plebs.Clear(); + + foreach (var creature in mObjectsManager.CreatureList) + { + if (creature.Faction == Faction.Kingdom) + { + if (!creature.IsDead) + { + if (creature is Knight) + { + if (creature.MovementState == MovementState.Idle && creature.IsAttacking == null) + WorldView.IdlingKnights.Add(creature); + } + } + } + else if (creature.Faction == Faction.Undead) + { + if (!creature.IsDead) + { + if (!(creature is Necromancer)) + WorldView.EnemyCount++; + else + WorldView.NecromancerHealth = (float) creature.Life / creature.MaxLife; + WorldView.Targets.Add(creature); + } + } + else if (creature.Faction == Faction.Plebs) + { + if (!creature.IsDead) + { + WorldView.Plebs.Add(creature); + } + } + + WorldView.PlebsCount = WorldView.Plebs.Count; + if (WorldView.InitialPlebsCount < WorldView.PlebsCount) + WorldView.InitialPlebsCount = WorldView.PlebsCount; + } + } + + private TimeSpan GetRandomTimeSpanSpawn() + { + var factor = Math.Max(0, 500 - WorldView.EnemyCount) / 500; + return TimeSpan.FromMilliseconds(mRandom.Next(mMaxWaitBaseMs)) + + TimeSpan.FromSeconds(mRandom.Next(factor * mMaxWaitAddMs)); + } + + /// + /// Take actions based on the previous percepts, the current strategy + /// and state. + /// + public void Act() + { + State = Strategy.Update(State, WorldView); + + var completedActions = Actions.Where( + a => a.State == ActionState.Done || a.State == ActionState.Failed).ToList(); + completedActions.ForEach(a => Actions.Remove(a)); + + if (State != AiState.Idle) + { + if (mTimeSpan >= mTimeSpanSpawn) + { + mTimeSpan -= mTimeSpanSpawn; + mTimeSpanSpawn = GetRandomTimeSpanSpawn(); + SpawnKnight(); + } + } + + switch (State) + { + case AiState.Idle: + // nothing do to when idling + return; + case AiState.AttackCreatures: + // let all idling soldiers attack some creatures + if (WorldView.Targets.Count > 0) + { + foreach (var creature in WorldView.IdlingKnights) + { + ICreature target = null; + var distance = float.MaxValue; + foreach (var c in WorldView.Targets) + { + var d = Vector2.Distance(c.Position, creature.Position); + if (d < distance) + { + distance = d; + target = c; + } + } + creature.IsAttacking = target; + } + } + break; + case AiState.DefendPeasants: + if (WorldView.Plebs.Count > 0) + { + foreach (var creature in WorldView.IdlingKnights) + { + ICreature target = null; + var distance = float.MaxValue; + var threshold = (int) (creature.AttackRadius * 0.8); + foreach (var c in WorldView.Plebs) + { + var d = Vector2.Distance(c.Position, creature.Position); + if (d <= threshold) + { + target = null; + break; + } + // attempt to avoid clustering + /*if (mObjectsManager.GetObjectsInRectangle(c.SelectionRectangle).OfType().Count() > 0) + { + continue; + }*/ + if (d < distance) + { + distance = d; + target = c; + } + } + if (target != null) + { + var offset = target.Position - creature.Position; + offset.Normalize(); + offset *= threshold; + Move(creature, target.Position + offset); + } + } + } + break; + case AiState.AttackNecromancer: + foreach (var c in WorldView.IdlingKnights) + { + c.IsAttacking = mObjectsManager.PlayerCharacter; + } + break; + } + } + + private void SpawnKnight() + { + var knight = mCreatureFactory.CreateKnight(); + var position = new Vector2(500, 500); + if (mObjectsManager.Castle != null) + position = mObjectsManager.Castle.Position; + var spawnAction = mActionFactory.CreateSpawnAction(knight, position); + Actions.Add(spawnAction); + } + + private void Move(ICreature creature, Vector2 destination) + { + var moveAction = mActionFactory.CreateMoveAction(creature, destination); + Actions.Add(moveAction); + } + } +} diff --git a/V3/AI/Internal/AttackStrategy.cs b/V3/AI/Internal/AttackStrategy.cs new file mode 100644 index 0000000..d108b1f --- /dev/null +++ b/V3/AI/Internal/AttackStrategy.cs @@ -0,0 +1,48 @@ +namespace V3.AI.Internal +{ + /// + /// A simple strategy for the computer player that tells him to attack the + /// enemy creatures. + /// + internal class AttackStrategy : IStrategy + { + /// + /// Updates the current state according to the game situtation. + /// + /// the current state + /// the current view of the game world + /// the next state indicated by this strategy + public AiState Update(AiState state, IWorldView worldView) + { + switch (state) + { + case AiState.Idle: + if (worldView.InitialPlebsCount - worldView.PlebsCount > 3) + { + return AiState.DefendPeasants; + } + break; + case AiState.DefendPeasants: + if (worldView.PlebsCount < worldView.InitialPlebsCount * 0.75 || worldView.EnemyCount > 20) + { + return AiState.AttackCreatures; + } + break; + case AiState.AttackCreatures: + if (worldView.NecromancerHealth < 0.1) + { + return AiState.AttackNecromancer; + } + break; + case AiState.AttackNecromancer: + if (worldView.NecromancerHealth >= 0.1) + { + return AiState.AttackCreatures; + } + break; + } + + return state; + } + } +} diff --git a/V3/AI/Internal/IActionFactory.cs b/V3/AI/Internal/IActionFactory.cs new file mode 100644 index 0000000..eb62222 --- /dev/null +++ b/V3/AI/Internal/IActionFactory.cs @@ -0,0 +1,27 @@ +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.AI.Internal +{ + /// + /// Creates IAction instances. Automatically implemented by Ninject. + /// + public interface IActionFactory + { + /// + /// Creates a new MoveAction to move the given creature to the given + /// destination. + /// + /// the creature to mvoe + /// the destination of the creature + MoveAction CreateMoveAction(ICreature creature, Vector2 destination); + + /// + /// Creates a new SpawnAction that spawns the given creature at the + /// given position. + /// + /// the creature to spawn + /// the spawn position + SpawnAction CreateSpawnAction(ICreature creature, Vector2 position); + } +} diff --git a/V3/AI/Internal/MoveAction.cs b/V3/AI/Internal/MoveAction.cs new file mode 100644 index 0000000..fcbba54 --- /dev/null +++ b/V3/AI/Internal/MoveAction.cs @@ -0,0 +1,53 @@ +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.AI.Internal +{ + /// + /// Moves a creature to a destination point. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public class MoveAction : AbstractAction + { + private ICreature mCreature; + private Vector2 mDestination; + + /// + /// Creates a new MoveAction to move the given creature to the given + /// destination. + /// + /// the creature to mvoe + /// the destination of the creature + public MoveAction(ICreature creature, Vector2 destination) + { + mCreature = creature; + mDestination = destination; + } + + /// + /// Start the execution of the action. + /// + public override void Start() + { + mCreature.Move(mDestination); + base.Start(); + } + + protected override ActionState GetNextState() + { + switch (mCreature.MovementState) + { + case MovementState.Idle: + return ActionState.Done; + case MovementState.Attacking: + case MovementState.Dying: + return ActionState.Failed; + case MovementState.Moving: + return ActionState.Executing; + default: + return ActionState.Failed; + } + } + + } +} diff --git a/V3/AI/Internal/SpawnAction.cs b/V3/AI/Internal/SpawnAction.cs new file mode 100644 index 0000000..4df6225 --- /dev/null +++ b/V3/AI/Internal/SpawnAction.cs @@ -0,0 +1,42 @@ +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.AI.Internal +{ + /// + /// Spawns a creature at a given position. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public class SpawnAction : AbstractAction + { + private readonly IObjectsManager mObjectsManager; + private ICreature mCreature; + private Vector2 mPosition; + + /// + /// Creates a new SpawnAction that spawns the given creature at the + /// given position. + /// + /// the linked objects manager + /// the creature to spawn + /// the spawn position + public SpawnAction(IObjectsManager objectsManager, ICreature creature, Vector2 position) + { + mObjectsManager = objectsManager; + mCreature = creature; + mPosition = position; + } + + public override void Start() + { + mCreature.Position = mPosition; + mObjectsManager.CreateCreature(mCreature); + base.Start(); + } + + protected override ActionState GetNextState() + { + return ActionState.Done; + } + } +} diff --git a/V3/AI/Internal/WorldView.cs b/V3/AI/Internal/WorldView.cs new file mode 100644 index 0000000..cedd0ae --- /dev/null +++ b/V3/AI/Internal/WorldView.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using V3.Objects; + +namespace V3.AI.Internal +{ + /// + /// Default implementation of IWorldView. + /// + internal class WorldView : IWorldView + { + public int EnemyCount { get; set; } + public int InitialPlebsCount { get; set; } + public int PlebsCount { get; set; } + public float NecromancerHealth { get; set; } + public List IdlingKnights { get; } = new List(); + public List Targets { get; } = new List(); + public List Plebs { get; } = new List(); + } +} diff --git a/V3/AchievementsAndStatistics.cs b/V3/AchievementsAndStatistics.cs new file mode 100644 index 0000000..65419d7 --- /dev/null +++ b/V3/AchievementsAndStatistics.cs @@ -0,0 +1,31 @@ +using System; + +namespace V3 +{ + /// + /// This is a class for all datas of the achievementsand the statistics. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class AchievementsAndStatistics + { + public bool mKillPrince = false; + public bool mKillKing = false; + public bool mHellsNotWaiting = false; + public bool mKaboom = false; + + public float mMarathonRunner = 0; + public float mIronMan = 0; + public int mMeatballCompany = 0; + public int mSkeletonHorseCavalry = 0; + public int mRightHandOfDeath = 0; + public int mMinimalist = 0; + public int mHundredDeadCorpses = 0; + public int mUndeadArmy = 0; + + public int mKilledCreatures = 00000; + public int mLostServants = 00000; + public float mWalkedDistance = 00000; + + public DateTime mUsedTime; + } +} diff --git a/V3/Bindings.cs b/V3/Bindings.cs new file mode 100644 index 0000000..cc9b193 --- /dev/null +++ b/V3/Bindings.cs @@ -0,0 +1,75 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Ninject.Extensions.Factory; +using Ninject.Modules; +using V3.AI; +using V3.AI.Internal; +using V3.Camera; +using V3.Data; +using V3.Data.Internal; +using V3.Effects; +using V3.Input; +using V3.Input.Internal; +using V3.Map; +using V3.Screens; +using V3.Objects; +using V3.Widgets; + +namespace V3 +{ + /// + /// Defines the bindings of constants, factories and singletons for the + /// Ninject dependency injection framework. + /// + public sealed class Bindings : NinjectModule + { + private readonly V3Game mGame; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + + /// + /// Creates a new Bindings instance for the given game and graphics + /// device manager. + /// + /// the game that uses this instance + /// the graphics device manager + /// instance to use in this instance + public Bindings(V3Game game, GraphicsDeviceManager graphicsDeviceManager) + { + mGame = game; + mGraphicsDeviceManager = graphicsDeviceManager; + } + + public override void Load() + { + // constants + Bind().ToConstant(mGame.Content); + Bind().ToConstant(mGame); + Bind().ToConstant(mGraphicsDeviceManager); + + // factories + Bind().ToFactory(); + Bind().ToFactory(); + Bind().ToFactory(); + Bind().ToFactory(); + Bind().ToFactory(); + + // singletons + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().ToSelf().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().ToSelf().InSingletonScope(); + Bind().ToSelf().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().ToSelf().InSingletonScope(); + + // regular bindings + Bind().To(); + Bind().To(); + Bind().To(); + } + } +} diff --git a/V3/CONTROLS.md b/V3/CONTROLS.md new file mode 100644 index 0000000..335f298 --- /dev/null +++ b/V3/CONTROLS.md @@ -0,0 +1,37 @@ +Controls +======== + +Mouse +----- + +* Clicking left mouse button: Selecting the clicked unit when in range +* Holding down left mouse button: Drawing a rectangle for selecting several units inside +* Clicking right mouse button: Move selected units to mouse position + +Keyboard +-------- + +* ESC : Open menu and pause game +* C : Toggle camera between scrolling and centered mode +* 1 : Trigger meatball explosion +* 2 : Summon zombies from corpses (or from a graveyard if you have no more minions) +* 3 : Transform five zombies to a meatball +* 4 : Transform one zombie to a skeleton +* 5 : Transform three skeletons to a horse + +Techdemo +-------- + +When pressing a specific key once and klicking on the map you can create one unit. + +* F1 : Create zombie +* F2 : Create skeleton +* F3 : Create peasant +* F4 : Create knight + +Cheats +------ + +* F5 : "Hippie mode" +* F6 : Change necromancer gender +* F8 : Toggle Fog of War on/off \ No newline at end of file diff --git a/V3/CREDITS.md b/V3/CREDITS.md new file mode 100644 index 0000000..c0e01e0 --- /dev/null +++ b/V3/CREDITS.md @@ -0,0 +1,51 @@ +Credits +======= + +Most of the content - especially sprites and map textures - is taken from the FLARE game. +http://flarerpg.org/ +https://github.com/clintbellanger/flare-game +"All of Flare's art and data files are released under CC-BY-SA 3.0. Later versions are permitted." + +The maps were created with the Tiled Map Editor . +Special thanks to Sabrina for pulling an all nighter and creating the large map for the main mission. + +Further content: +---------------- +* Castle sprite from Feudal Wars (CC0) + +* Animated particle effects #1 and #2 by para (CC0) + + +* Explosion animation and sound by WrathGames Studio (CC-BY 3.0) + + +* The Fleischklops / Meatball sprite is licenced under CC BY 3.0. + It was created using Clint Bellanger's Zombie (CC BY 3.0) + http://opengameart.org/content/zombie-0 + +Title screen: +------------- +* "The Triumph of Death" by Pieter Bruegel the Elder (1525 - 1569) + + +Music: +------ +* Title screen music by Kosta T / Konstantin Trokay (CC BY-NC 4.0) + +* Game screen music + + +Sounds: +------- +* Wet squish, slurp impacts by Independent.nu (CC0): + +* High Quality Explosions by Michel Baradari (CC-BY 3.0): + +* The Skeleton Horse sound + +* The Knight sound + +* The Meatball sound + +* The walking sound of the remaining creatures + \ No newline at end of file diff --git a/V3/Camera/CameraCentered.cs b/V3/Camera/CameraCentered.cs new file mode 100644 index 0000000..cd04209 --- /dev/null +++ b/V3/Camera/CameraCentered.cs @@ -0,0 +1,57 @@ +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.Camera +{ + /// + /// This is the Camera Class for a player-centered camera mode. Does not go outside the map. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class CameraCentered : ICamera + { + public int MapPixelWidth { get; set; } + public int MapPixelHeight { get; set; } + private int mMaxX; + private int mMaxY; + public Matrix Transform { get; set; } + private Point mCamCenter; + public Vector2 Location { get { return mCamCenter.ToVector2(); } set { mCamCenter = value.ToPoint(); } } + public Point ScreenSize => new Point(mGraphicsDeviceManager.GraphicsDevice.Viewport.Width, mGraphicsDeviceManager.GraphicsDevice.Viewport.Height); + public Rectangle ScreenRectangle => new Rectangle(mCamCenter, ScreenSize); + + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + + public CameraCentered(GraphicsDeviceManager graphicsDeviceManager) + { + mGraphicsDeviceManager = graphicsDeviceManager; + } + + private int ScreenWidth() + { + return mGraphicsDeviceManager.GraphicsDevice.Viewport.Width; + } + + private int ScreenHeight() + { + return mGraphicsDeviceManager.GraphicsDevice.Viewport.Height; + } + + /// + /// Updates the position of the camera related to the player's position. + /// + public void Update(ICreature player) + { + /*The center of the camera is by default in the upper left corner. To get the player in center, + simply substract the half of the screen values. Does not go outside the map. + */ + mMaxX = MapPixelWidth - ScreenWidth(); + mMaxY = MapPixelHeight / 2 - ScreenHeight(); + + mCamCenter = new Point(MathHelper.Clamp((int)(player.Position.X - ScreenWidth() * 0.5f), 0, mMaxX), + MathHelper.Clamp((int)(player.Position.Y - ScreenHeight() * 0.5f), 0, mMaxY)); + + //Transform matrix for the camera to make sure it is moving. + Transform = Matrix.CreateTranslation(new Vector3(-mCamCenter.ToVector2(), 0)); + } + } +} \ No newline at end of file diff --git a/V3/Camera/CameraManager.cs b/V3/Camera/CameraManager.cs new file mode 100644 index 0000000..b4d502e --- /dev/null +++ b/V3/Camera/CameraManager.cs @@ -0,0 +1,71 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using V3.Data; +using V3.Objects; + +namespace V3.Camera +{ + /// + /// Stores and provides access to the possible cameras. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class CameraManager + { + private readonly IOptionsManager mOptionsManager; + private readonly CameraCentered mCameraCentered; + private readonly CameraScrolling mCameraScrolling; + + /// + /// Creates a new CameraManager. + /// + public CameraManager(CameraCentered cameraCentered, + CameraScrolling cameraScrolling, IOptionsManager optionsManager) + { + mCameraCentered = cameraCentered; + mCameraScrolling = cameraScrolling; + mOptionsManager = optionsManager; + } + + /// + /// Initializes the cameras with the given map data. + /// + public void Initialize(Point mapPixelSize) + { + // TODO: Warum *2? Irgendwas stimmt bei der Interpretation hier nicht. + var mapPixelHeight = mapPixelSize.Y * 2; + var mapPixelWidth = mapPixelSize.X; + var cameras = new List { mCameraCentered, mCameraScrolling }; + foreach (var camera in cameras) + { + camera.MapPixelHeight = mapPixelHeight; + camera.MapPixelWidth = mapPixelWidth; + } + } + + /// + /// Updates the cameras. + /// + public void Update(ICreature creature) + { + GetCamera().Update(creature); + if (mOptionsManager.Options.CameraType != CameraType.Scrolling) + mCameraScrolling.Location = GetCamera().Location; + } + + /// + /// Returns the currently selected camera. + /// + public ICamera GetCamera() + { + switch (mOptionsManager.Options.CameraType) + { + case CameraType.Centered: + return mCameraCentered; + case CameraType.Scrolling: + return mCameraScrolling; + default: + return mCameraScrolling; + } + } + } +} diff --git a/V3/Camera/CameraScrolling.cs b/V3/Camera/CameraScrolling.cs new file mode 100644 index 0000000..72e4911 --- /dev/null +++ b/V3/Camera/CameraScrolling.cs @@ -0,0 +1,96 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using V3.Objects; +using MathHelper = Microsoft.Xna.Framework.MathHelper; +using Vector2 = Microsoft.Xna.Framework.Vector2; + +namespace V3.Camera +{ + /// + /// This is the camera class for a map-scrolling camera mode. Does not move over the map. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class CameraScrolling : ICamera + { + public int MapPixelWidth { get; set; } + public int MapPixelHeight { get; set; } + private const int MinOffset = 10; + private const int CameraSpeed = 10; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + private Point mLocation; + public Matrix Transform { get; set; } + private int mMaxX; + private int mMaxY; + public Vector2 Location {get {return mLocation.ToVector2();} set { mLocation = value.ToPoint(); } } + public Point ScreenSize => new Point(mGraphicsDeviceManager.GraphicsDevice.Viewport.Width, mGraphicsDeviceManager.GraphicsDevice.Viewport.Height); + public Rectangle ScreenRectangle => new Rectangle(mLocation, ScreenSize); + + public CameraScrolling(GraphicsDeviceManager graphicsDeviceManager) + { + mGraphicsDeviceManager = graphicsDeviceManager; + } + + public void Update(ICreature player) + { + var viewport = mGraphicsDeviceManager.GraphicsDevice.Viewport; + + mMaxX = MapPixelWidth - viewport.Width; + mMaxY = MapPixelHeight / 2 - viewport.Height; + + var mouse = Mouse.GetState(); + if (mouse.X < MinOffset) + { + MoveCameraLeft(); + } + + if (mouse.X > viewport.Width - MinOffset) + { + MoveCameraRight(); + } + + if (mouse.Y < MinOffset) + { + MoveCameraDown(); + } + + if (mouse.Y > viewport.Height - MinOffset) + { + MoveCameraUp(); + } + Transform = Matrix.CreateTranslation(new Vector3(-mLocation.ToVector2(), 0)); + } + + /// + /// Move the Camera to the left. Does not go outside the map. + /// + private void MoveCameraLeft() + { + mLocation.X = MathHelper.Clamp(mLocation.X - CameraSpeed, 0, mMaxX); + } + + /// + /// Move the Camera to the right. Does not go outside the map. + /// + private void MoveCameraRight() + { + mLocation.X = MathHelper.Clamp(mLocation.X + CameraSpeed, 0, mMaxX); + } + + /// + /// Move the Camera up. Does not go outside the map. + /// + private void MoveCameraUp() + { + mLocation.Y = MathHelper.Clamp(mLocation.Y + CameraSpeed, 0, mMaxY); + } + + + /// + /// Move the Camera down. Does not go outside the map. + /// + private void MoveCameraDown() + { + mLocation.Y = MathHelper.Clamp(mLocation.Y - CameraSpeed, 0, mMaxY); + } + } +} \ No newline at end of file diff --git a/V3/Camera/CameraType.cs b/V3/Camera/CameraType.cs new file mode 100644 index 0000000..4e373d9 --- /dev/null +++ b/V3/Camera/CameraType.cs @@ -0,0 +1,8 @@ +namespace V3.Camera +{ + public enum CameraType + { + Centered, + Scrolling + } +} diff --git a/V3/Camera/ICamera.cs b/V3/Camera/ICamera.cs new file mode 100644 index 0000000..4a8bbcd --- /dev/null +++ b/V3/Camera/ICamera.cs @@ -0,0 +1,18 @@ +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.Camera +{ + public interface ICamera + { + Matrix Transform { get; set; } + Vector2 Location { get; set; } + Point ScreenSize { get; } + Rectangle ScreenRectangle { get; } + + void Update(ICreature player); + + int MapPixelWidth { get; set; } + int MapPixelHeight { get; set; } + } + } diff --git a/V3/ClassDiagram1.cd b/V3/ClassDiagram1.cd new file mode 100644 index 0000000..7b89419 --- /dev/null +++ b/V3/ClassDiagram1.cd @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/V3/Content/Buttons/Button-01.png b/V3/Content/Buttons/Button-01.png new file mode 100644 index 0000000..7c1f22d Binary files /dev/null and b/V3/Content/Buttons/Button-01.png differ diff --git a/V3/Content/Buttons/Button-01_Pressed.png b/V3/Content/Buttons/Button-01_Pressed.png new file mode 100644 index 0000000..c67cf34 Binary files /dev/null and b/V3/Content/Buttons/Button-01_Pressed.png differ diff --git a/V3/Content/Buttons/Button-02.png b/V3/Content/Buttons/Button-02.png new file mode 100644 index 0000000..123a375 Binary files /dev/null and b/V3/Content/Buttons/Button-02.png differ diff --git a/V3/Content/Buttons/Button-02_Pressed.png b/V3/Content/Buttons/Button-02_Pressed.png new file mode 100644 index 0000000..a017676 Binary files /dev/null and b/V3/Content/Buttons/Button-02_Pressed.png differ diff --git a/V3/Content/Buttons/Button-03.png b/V3/Content/Buttons/Button-03.png new file mode 100644 index 0000000..a06547d Binary files /dev/null and b/V3/Content/Buttons/Button-03.png differ diff --git a/V3/Content/Buttons/Button-03_Pressed.png b/V3/Content/Buttons/Button-03_Pressed.png new file mode 100644 index 0000000..a2fe634 Binary files /dev/null and b/V3/Content/Buttons/Button-03_Pressed.png differ diff --git a/V3/Content/Buttons/Button-04.png b/V3/Content/Buttons/Button-04.png new file mode 100644 index 0000000..42a60da Binary files /dev/null and b/V3/Content/Buttons/Button-04.png differ diff --git a/V3/Content/Buttons/Button-04_Pressed.png b/V3/Content/Buttons/Button-04_Pressed.png new file mode 100644 index 0000000..0cca164 Binary files /dev/null and b/V3/Content/Buttons/Button-04_Pressed.png differ diff --git a/V3/Content/Buttons/Button-05.png b/V3/Content/Buttons/Button-05.png new file mode 100644 index 0000000..3a2d99c Binary files /dev/null and b/V3/Content/Buttons/Button-05.png differ diff --git a/V3/Content/Buttons/Button-05_Pressed.png b/V3/Content/Buttons/Button-05_Pressed.png new file mode 100644 index 0000000..86b8b9e Binary files /dev/null and b/V3/Content/Buttons/Button-05_Pressed.png differ diff --git a/V3/Content/Buttons/Button-06.png b/V3/Content/Buttons/Button-06.png new file mode 100644 index 0000000..1bc3448 Binary files /dev/null and b/V3/Content/Buttons/Button-06.png differ diff --git a/V3/Content/Buttons/Button-06_Pressed.png b/V3/Content/Buttons/Button-06_Pressed.png new file mode 100644 index 0000000..5a6cc1e Binary files /dev/null and b/V3/Content/Buttons/Button-06_Pressed.png differ diff --git a/V3/Content/Buttons/Button-07.png b/V3/Content/Buttons/Button-07.png new file mode 100644 index 0000000..422e445 Binary files /dev/null and b/V3/Content/Buttons/Button-07.png differ diff --git a/V3/Content/Buttons/Button-07_Pressed.png b/V3/Content/Buttons/Button-07_Pressed.png new file mode 100644 index 0000000..5cbe2b9 Binary files /dev/null and b/V3/Content/Buttons/Button-07_Pressed.png differ diff --git a/V3/Content/Content.mgcb b/V3/Content/Content.mgcb new file mode 100644 index 0000000..bbaf13b --- /dev/null +++ b/V3/Content/Content.mgcb @@ -0,0 +1,1092 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + +#begin Fonts/MenuFont.spritefont +/importer:FontDescriptionImporter +/processor:FontDescriptionProcessor +/processorParam:TextureFormat=Color +/build:Fonts/MenuFont.spritefont + +#begin Sprites/zombie.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/zombie.png + +#begin Textures/grassland.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/grassland.png + +#begin Textures/grassland_trees.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/grassland_trees.png + +#begin Textures/grassland_water.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/grassland_water.png + +#begin Textures/houses_front.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/houses_front.png + +#begin Textures/houses_rear.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/houses_rear.png + +#begin Sprites/skeleton.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/skeleton.png + +#begin Sprites/necromancer.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/necromancer.png + +#begin Sounds/walking.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/walking.wav + +#begin Maps/map_grassland.tmx +/copy:Maps/map_grassland.tmx + +#begin Textures/pathfinder.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/pathfinder.png + +#begin Sprites/WhiteRectangle.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/WhiteRectangle.png + +#begin Fonts/UnitFont.spritefont +/importer:FontDescriptionImporter +/processor:FontDescriptionProcessor +/processorParam:TextureFormat=Color +/build:Fonts/UnitFont.spritefont + +#begin Maps/work_in_progress.tmx +/copy:Maps/work_in_progress.tmx + +#begin Sprites/shield.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/shield.png + +#begin Sprites/longsword.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/longsword.png + +#begin Sprites/head_plate.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_plate.png + +#begin Sprites/head_plate_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_plate_female.png + +#begin Sprites/plate.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/plate.png + +#begin Sprites/cloth.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/cloth.png + +#begin Sprites/shield_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/shield_female.png + +#begin Sprites/longsword_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/longsword_female.png + +#begin Sprites/plate_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/plate_female.png + +#begin Sprites/cloth_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/cloth_female.png + +#begin Sprites/head_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_female.png + +#begin Sprites/nude_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/nude_female.png + +#begin Sprites/head_bald.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_bald.png + +#begin Sprites/head.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head.png + +#begin Sprites/nude.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/nude.png + +#begin Sprites/selection.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/selection.png + +#begin Sprites/skeleton_horse.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/skeleton_horse.png + +#begin Sprites/fleischklops.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/fleischklops.png + +#begin Sprites/cloud.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/cloud.png + +#begin Sprites/prince.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/prince.png + +#begin Buttons/Button-01.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-01.png + +#begin Buttons/Button-02.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-02.png + +#begin Buttons/Button-03.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-03.png + +#begin Buttons/Button-04.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-04.png + +#begin Buttons/Button-05.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-05.png + +#begin Buttons/Button-06.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-06.png + +#begin Buttons/Button-07.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-07.png + +#begin Textures/castle.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/castle.png + +#begin Menu/arrow_white.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Menu/arrow_white.png + +#begin Menu/mainscreen.jpg +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Menu/mainscreen.jpg + +#begin Sounds/Kosta_T_-_06.mp3 +/importer:Mp3Importer +/processor:SongProcessor +/processorParam:Quality=Best +/build:Sounds/Kosta_T_-_06.mp3 + +#begin Maps/techdemo.tmx +/copy:Maps/techdemo.tmx + +#begin Textures/EmptyPixel.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Textures/EmptyPixel.png + +#begin Sounds/Knight.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/Knight.wav + +#begin Sounds/SkeletonHorse.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/SkeletonHorse.wav + +#begin Sounds/punch.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/punch.wav + +#begin Sounds/Mummy_Zombie-SoundBible.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/Mummy_Zombie-SoundBible.wav + +#begin Sounds/Monster_Gigante-Doberman-1334685792.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/Monster_Gigante-Doberman-1334685792.wav + +#begin Menu/Titel.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Menu/Titel.png + +#begin Sprites/skeleton_rider.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/skeleton_rider.png + +#begin Effects/particlefx_03.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/particlefx_03.png + +#begin Effects/particlefx_04.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/particlefx_04.png + +#begin Effects/particlefx_05.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/particlefx_05.png + +#begin Effects/blood_hit_01.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_01.png + +#begin Effects/blood_hit_02.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_02.png + +#begin Effects/blood_hit_03.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_03.png + +#begin Effects/blood_hit_04.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_04.png + +#begin Effects/blood_hit_05.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_05.png + +#begin Effects/blood_hit_06.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_06.png + +#begin Effects/blood_hit_08.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/blood_hit_08.png + +#begin Effects/explosion.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/explosion.png + +#begin Sounds/explosion1.ogg +/importer:OggImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/explosion1.ogg + +#begin Sounds/impactsplat01.ogg +/importer:OggImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/impactsplat01.ogg + +#begin Sprites/skeleton_elite.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/skeleton_elite.png + +#begin Sprites/staff_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/staff_female.png + +#begin Sprites/staff.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/staff.png + +#begin Sprites/necromancer_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/necromancer_female.png + +#begin Sprites/ellipse.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/ellipse.png + +#begin Sprites/fog.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/fog.png + +#begin Buttons/Button-01_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-01_Pressed.png + +#begin Buttons/Button-02_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-02_Pressed.png + +#begin Buttons/Button-03_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-03_Pressed.png + +#begin Buttons/Button-04_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-04_Pressed.png + +#begin Buttons/Button-05_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-05_Pressed.png + +#begin Buttons/Button-06_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-06_Pressed.png + +#begin Buttons/Button-07_Pressed.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Buttons/Button-07_Pressed.png + +#begin Sprites/chain_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/chain_female.png + +#begin Sprites/head_chain_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_chain_female.png + +#begin Sprites/buckler_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/buckler_female.png + +#begin Sprites/shortsword_female.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/shortsword_female.png + +#begin Sprites/buckler.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/buckler.png + +#begin Sprites/shortsword.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/shortsword.png + +#begin Sprites/head_chain.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/head_chain.png + +#begin Sprites/chain.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/chain.png + +#begin Sprites/arrows.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/arrows.png + +#begin Effects/quake.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Effects/quake.png + +#begin Sprites/skeleton_archer.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/skeleton_archer.png + +#begin Sprites/zombie_club.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/zombie_club.png + +#begin Sprites/king.png +/importer:TextureImporter +/processor:TextureProcessor +/processorParam:ColorKeyColor=255,0,255,255 +/processorParam:ColorKeyEnabled=True +/processorParam:GenerateMipmaps=False +/processorParam:PremultiplyAlpha=True +/processorParam:ResizeToPowerOfTwo=False +/processorParam:MakeSquare=False +/processorParam:TextureFormat=Color +/build:Sprites/king.png + +#begin Fonts/DeathFont.spritefont +/importer:FontDescriptionImporter +/processor:FontDescriptionProcessor +/processorParam:TextureFormat=Color +/build:Fonts/DeathFont.spritefont + +#begin Sounds/Afraid_to_Go.mp3 +/importer:Mp3Importer +/processor:SongProcessor +/processorParam:Quality=Best +/build:Sounds/Afraid_to_Go.mp3 + +#begin Fonts/VictoryFont.spritefont +/importer:FontDescriptionImporter +/processor:FontDescriptionProcessor +/processorParam:TextureFormat=Color +/build:Fonts/VictoryFont.spritefont + +#begin Sounds/explode.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/explode.wav + +#begin Sounds/explodemini.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/explodemini.wav + +#begin Sounds/horse.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/horse.wav + +#begin Sounds/zonk2.wav +/importer:WavImporter +/processor:SoundEffectProcessor +/processorParam:Quality=Best +/build:Sounds/zonk2.wav + diff --git a/V3/Content/Effects/blood_hit_01.png b/V3/Content/Effects/blood_hit_01.png new file mode 100644 index 0000000..4ce41d8 Binary files /dev/null and b/V3/Content/Effects/blood_hit_01.png differ diff --git a/V3/Content/Effects/blood_hit_02.png b/V3/Content/Effects/blood_hit_02.png new file mode 100644 index 0000000..b4ce9ba Binary files /dev/null and b/V3/Content/Effects/blood_hit_02.png differ diff --git a/V3/Content/Effects/blood_hit_03.png b/V3/Content/Effects/blood_hit_03.png new file mode 100644 index 0000000..0f827f4 Binary files /dev/null and b/V3/Content/Effects/blood_hit_03.png differ diff --git a/V3/Content/Effects/blood_hit_04.png b/V3/Content/Effects/blood_hit_04.png new file mode 100644 index 0000000..bf122a2 Binary files /dev/null and b/V3/Content/Effects/blood_hit_04.png differ diff --git a/V3/Content/Effects/blood_hit_05.png b/V3/Content/Effects/blood_hit_05.png new file mode 100644 index 0000000..a177ce9 Binary files /dev/null and b/V3/Content/Effects/blood_hit_05.png differ diff --git a/V3/Content/Effects/blood_hit_06.png b/V3/Content/Effects/blood_hit_06.png new file mode 100644 index 0000000..51aa729 Binary files /dev/null and b/V3/Content/Effects/blood_hit_06.png differ diff --git a/V3/Content/Effects/blood_hit_08.png b/V3/Content/Effects/blood_hit_08.png new file mode 100644 index 0000000..87b6794 Binary files /dev/null and b/V3/Content/Effects/blood_hit_08.png differ diff --git a/V3/Content/Effects/explosion.png b/V3/Content/Effects/explosion.png new file mode 100644 index 0000000..0f4f3e9 Binary files /dev/null and b/V3/Content/Effects/explosion.png differ diff --git a/V3/Content/Effects/particlefx_03.png b/V3/Content/Effects/particlefx_03.png new file mode 100644 index 0000000..2649c85 Binary files /dev/null and b/V3/Content/Effects/particlefx_03.png differ diff --git a/V3/Content/Effects/particlefx_04.png b/V3/Content/Effects/particlefx_04.png new file mode 100644 index 0000000..346695e Binary files /dev/null and b/V3/Content/Effects/particlefx_04.png differ diff --git a/V3/Content/Effects/particlefx_05.png b/V3/Content/Effects/particlefx_05.png new file mode 100644 index 0000000..d046357 Binary files /dev/null and b/V3/Content/Effects/particlefx_05.png differ diff --git a/V3/Content/Effects/quake.png b/V3/Content/Effects/quake.png new file mode 100644 index 0000000..6fe7ad0 Binary files /dev/null and b/V3/Content/Effects/quake.png differ diff --git a/V3/Content/Fonts/Blutschrift.ttf b/V3/Content/Fonts/Blutschrift.ttf new file mode 100644 index 0000000..da803c1 Binary files /dev/null and b/V3/Content/Fonts/Blutschrift.ttf differ diff --git a/V3/Content/Fonts/DeathFont.spritefont b/V3/Content/Fonts/DeathFont.spritefont new file mode 100644 index 0000000..8cbab91 --- /dev/null +++ b/V3/Content/Fonts/DeathFont.spritefont @@ -0,0 +1,50 @@ + + + + Blutschrift + 50 + 3 + + + + + ~ + + + + ä + ä + + + + ö + ö + + + + ü + ü + + + + Ä + Ä + + + + Ö + Ö + + + + Ü + Ü + + + + ß + ß + + + + \ No newline at end of file diff --git a/V3/Content/Fonts/DejaVuSans.ttf b/V3/Content/Fonts/DejaVuSans.ttf new file mode 100644 index 0000000..de12789 Binary files /dev/null and b/V3/Content/Fonts/DejaVuSans.ttf differ diff --git a/V3/Content/Fonts/MenuFont.spritefont b/V3/Content/Fonts/MenuFont.spritefont new file mode 100644 index 0000000..e6362fb --- /dev/null +++ b/V3/Content/Fonts/MenuFont.spritefont @@ -0,0 +1,50 @@ + + + + grabstein + 20 + 3 + + + + + ~ + + + + ä + ä + + + + ö + ö + + + + ü + ü + + + + Ä + Ä + + + + Ö + Ö + + + + Ü + Ü + + + + ß + ß + + + + \ No newline at end of file diff --git a/V3/Content/Fonts/Siegesschriftzug.ttf b/V3/Content/Fonts/Siegesschriftzug.ttf new file mode 100644 index 0000000..59dd36d Binary files /dev/null and b/V3/Content/Fonts/Siegesschriftzug.ttf differ diff --git a/V3/Content/Fonts/UnitFont.spritefont b/V3/Content/Fonts/UnitFont.spritefont new file mode 100644 index 0000000..fa4bf9f --- /dev/null +++ b/V3/Content/Fonts/UnitFont.spritefont @@ -0,0 +1,50 @@ + + + + grabstein + 12 + 3 + + + + + ~ + + + + ä + ä + + + + ö + ö + + + + ü + ü + + + + Ä + Ä + + + + Ö + Ö + + + + Ü + Ü + + + + ß + ß + + + + \ No newline at end of file diff --git a/V3/Content/Fonts/VictoryFont.spritefont b/V3/Content/Fonts/VictoryFont.spritefont new file mode 100644 index 0000000..28d695a --- /dev/null +++ b/V3/Content/Fonts/VictoryFont.spritefont @@ -0,0 +1,50 @@ + + + + Siegesschriftzug + 50 + 3 + + + + + ~ + + + + ä + ä + + + + ö + ö + + + + ü + ü + + + + Ä + Ä + + + + Ö + Ö + + + + Ü + Ü + + + + ß + ß + + + + \ No newline at end of file diff --git a/V3/Content/Fonts/grabstein.ttf b/V3/Content/Fonts/grabstein.ttf new file mode 100644 index 0000000..711b3a1 Binary files /dev/null and b/V3/Content/Fonts/grabstein.ttf differ diff --git a/V3/Content/Maps/map_grassland.tmx b/V3/Content/Maps/map_grassland.tmx new file mode 100644 index 0000000..9162f2a --- /dev/null +++ b/V3/Content/Maps/map_grassland.tmx @@ -0,0 +1,988 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,153,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,145,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,156,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,152,151,1,1,1,1,1,1,1,1,1,1,1,1,1,24,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,155,1,1,1,1,1,1,1,1,1,1,1,1,1,24,24,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,24,23,24,24,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,24,23,23,23,24,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,24,23,23,23,23,23,32,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +153,153,153,1,1,1,153,1,1,1,1,1,1,1,24,23,29,29,29,23,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +165,165,150,153,153,149,154,1,1,1,1,1,1,24,23,1,1,1,1,1,1,1,1,1,153,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +177,163,163,165,165,165,151,1,1,1,1,1,1,24,23,1,1,1,1,1,1,1,1,1,145,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +155,155,155,148,177,151,1,1,1,1,1,1,24,23,1,1,1,1,1,1,1,1,1,145,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,155,155,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,145,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,145,187,187,187,194,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,145,187,187,187,198,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,149,187,187,187,208,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,156,187,187,187,206,187,187,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,152,187,187,198,187,187,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,152,187,187,187,187,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,164,187,187,187,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,160,187,187,187,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,152,187,187,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,164,187,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,160,187,187,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,164,187,187,158,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,187,187,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,31,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,187,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,23,23,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,187,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,23,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,187,150,1,1,1,1,1,1,1,1,153,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,187,150,1,1,1,1,1,1,1,149,146,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,187,154,1,1,1,1,1,1,149,181,146,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,166,1,1,1,1,1,1,149,177,181,146,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,192,187,150,1,1,1,1,1,156,177,177,181,150,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,187,187,154,1,1,1,1,1,164,177,181,181,150,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,164,187,166,1,1,1,1,1,145,177,181,181,181,150,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,187,187,150,1,1,1,1,145,177,181,181,181,181,150,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,1,1,145,177,181,181,181,181,181,146,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,1,145,177,181,181,181,181,181,177,146,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,187,187,150,1,145,177,180,167,163,163,163,163,163,154,1,1,1,1,1,1,1, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,146,145,180,180,151,155,155,155,155,155,155,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,165,180,180,166,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,164,180,180,180,180,180,154,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,156,180,180,180,180,180,166,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,180,180,180,154,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,180,180,166,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,180,180,154,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,180,180,167,151,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,148,167,151,159,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,159,159,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, +11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11 + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,128,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,216,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,0,0,0,0, +0,0,0,0,0,0,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,83,0,0,0,0,83,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,127,0,226,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +126,109,0,0,0,106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,99,0,0,99,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,144,0,0,0,0,0,0,0,133,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,106,0,0,0,0,133,0,99,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,0,0,0,0,0,0,0,0,0,0,0,0,135,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,214,0,0,0,0,0,0,0,135,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,0,0,127,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,113,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,210,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,125,0,103,0,0,0,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,0,0,0,0,0,99,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,144,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,0,0, +0,0,0,0,88,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,218,110,110,110,110,0,0,0,0,103,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,99,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,0,0,0,0,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,98,117,0,0,0,0,99,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,218,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,209,0,210,0,211,0,0,0,224,0,225,0,226,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,233,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,212,0,213,0,214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,221,0,222,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,215,0,216,0,217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,228,0,229,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,218,0,219,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,230,0,231,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V3/Content/Maps/techdemo.tmx b/V3/Content/Maps/techdemo.tmx new file mode 100644 index 0000000..b26a064 --- /dev/null +++ b/V3/Content/Maps/techdemo.tmx @@ -0,0 +1,1170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,9,8,3,3,3,7,16,9,16,1,10,7,8,7,10,3,4,5,7,1,11,8,8,6,2,10,16,4,11,5,2,9,9,1,15,7,13,3,8,10,6,16,11,13,16,11,4,0, +0,0,11,10,1,13,16,11,16,14,10,15,6,16,2,11,13,4,2,11,2,15,12,14,8,10,4,8,7,4,3,1,10,16,8,8,1,4,5,12,16,13,1,5,2,11,7,13,3,3, +0,3,3,15,8,16,7,7,6,5,3,8,4,1,7,2,9,5,2,9,14,6,8,1,15,10,12,2,12,11,8,8,4,3,5,14,13,3,1,5,11,9,10,15,7,10,3,15,12,0, +0,4,1,3,13,2,11,9,8,9,12,7,8,1,14,15,11,9,4,15,10,7,9,8,2,13,2,7,14,2,12,1,14,7,11,3,10,6,13,2,6,1,8,14,11,2,10,11,11,11, +3,7,10,12,10,5,9,9,5,2,16,4,7,14,2,10,6,16,9,12,1,7,8,3,12,6,5,16,3,9,16,7,6,16,14,7,15,3,8,16,12,16,3,14,1,13,5,15,11,0, +0,2,7,5,4,4,2,2,16,2,10,13,14,14,7,9,9,7,11,1,13,8,7,15,15,7,6,7,1,9,3,13,4,13,2,15,3,1,5,7,6,15,11,14,1,11,15,7,6,8, +16,16,2,9,13,14,16,1,12,14,4,12,14,16,11,13,16,11,16,3,8,4,7,5,9,8,14,8,13,16,16,9,11,14,14,16,4,2,8,16,4,2,6,7,16,16,12,12,9,0, +0,1,16,2,16,3,6,8,8,7,7,3,3,6,10,11,15,9,6,10,12,8,2,8,9,15,8,1,7,8,14,15,8,13,15,13,11,10,4,7,3,11,8,9,3,13,4,1,14,12, +8,14,16,5,10,15,1,11,6,13,1,2,5,2,16,3,15,9,13,7,9,7,5,5,8,4,3,1,16,4,3,16,16,10,11,4,10,7,5,14,11,11,4,12,1,6,14,13,7,0, +0,10,15,4,10,6,14,5,3,15,13,10,1,10,1,11,3,15,16,3,11,12,9,16,16,2,12,8,13,9,14,3,1,10,9,14,2,6,12,11,7,16,10,16,15,1,11,7,11,5, +12,4,5,3,12,2,8,1,3,11,16,13,9,5,6,6,9,10,6,1,16,6,15,1,14,7,1,14,5,14,1,2,9,14,3,10,2,13,16,5,10,3,4,4,12,11,11,12,8,0, +0,7,16,1,11,2,14,16,9,7,7,1,7,4,6,8,9,3,8,2,10,4,8,3,16,15,6,8,8,6,13,7,8,4,13,15,14,11,2,7,2,6,16,13,3,8,1,9,8,14, +8,8,7,13,15,7,2,4,15,13,6,16,10,14,1,11,8,5,5,3,8,6,13,13,16,8,10,7,10,12,2,2,9,7,2,7,7,6,15,7,1,11,3,7,14,16,16,4,11,0, +0,4,14,16,13,6,3,6,7,1,14,6,4,8,11,11,16,12,6,12,2,9,3,11,14,9,6,9,6,3,13,1,6,8,4,13,9,7,3,2,5,12,15,16,12,15,9,8,15,4, +8,10,16,11,1,11,10,11,13,8,12,10,3,9,2,13,6,1,4,4,1,12,3,9,13,3,11,1,10,7,3,11,5,5,12,2,3,5,3,10,7,7,13,1,11,9,12,1,5,0, +0,7,16,9,7,7,14,5,11,6,10,9,5,16,1,10,3,16,16,12,4,4,8,3,6,8,7,6,9,9,13,10,13,7,11,5,2,16,16,14,10,3,14,13,6,14,7,9,8,4, +12,9,9,14,3,15,13,7,11,1,16,9,1,16,11,12,15,11,8,7,13,2,16,15,2,1,7,10,4,2,3,8,6,16,8,10,12,3,6,1,6,16,15,11,4,15,1,2,4,0, +0,4,8,13,6,9,13,7,2,1,7,14,5,10,9,13,7,10,11,3,16,10,10,5,1,9,8,9,12,9,10,14,10,2,9,3,6,13,5,16,2,13,2,14,3,4,5,13,3,13, +5,11,11,3,9,12,2,11,3,7,14,5,3,15,10,4,12,9,16,14,2,13,15,13,13,4,7,10,6,11,12,5,10,1,3,13,8,7,3,5,1,1,9,3,9,6,15,13,6,0, +0,14,3,15,7,13,11,7,14,14,6,16,9,15,11,1,4,5,12,13,4,13,2,14,9,14,1,6,7,6,2,15,15,12,10,14,8,1,3,13,2,12,3,2,5,14,5,10,3,16, +7,9,4,8,16,5,5,3,7,15,4,15,3,6,11,5,1,14,12,5,5,2,11,5,7,4,8,1,9,11,4,14,1,6,10,4,12,10,10,3,15,2,13,4,3,1,15,2,11,0, +0,11,11,9,16,15,16,6,5,16,12,13,16,10,5,7,15,3,15,7,12,14,11,16,12,11,4,15,4,6,5,15,3,7,3,5,4,3,16,7,16,13,11,3,11,1,15,6,8,12, +8,4,11,13,11,14,9,14,11,15,11,14,9,11,14,7,16,4,13,14,6,5,11,4,13,1,5,2,15,10,3,15,2,10,10,9,6,4,5,11,6,9,13,9,6,2,4,1,7,0, +0,10,3,13,10,8,15,2,12,14,12,10,4,16,2,8,2,15,11,16,8,16,1,6,7,7,14,14,4,9,14,14,16,11,10,11,16,3,1,11,6,7,12,4,9,14,11,13,14,14, +7,11,4,11,7,6,5,12,11,7,14,10,3,8,10,1,2,5,14,10,6,7,3,12,12,3,14,16,2,2,16,9,1,5,13,11,3,1,5,8,15,7,7,1,12,6,15,5,14,0, +0,13,6,10,12,13,1,16,11,3,2,5,12,16,2,14,16,9,11,2,14,9,16,12,1,13,5,13,10,8,4,10,11,16,12,12,13,2,15,2,14,14,5,12,14,9,9,4,4,11, +6,6,10,16,10,2,6,5,8,6,1,15,12,3,5,9,5,16,4,2,1,3,15,8,6,5,9,16,6,3,9,14,12,11,10,11,1,14,5,16,2,15,10,11,14,6,10,10,8,0, +0,4,13,6,16,1,6,4,8,1,2,1,14,2,14,15,10,10,2,8,16,9,12,1,11,5,4,3,14,14,9,4,6,13,4,16,8,2,7,12,16,7,9,6,4,14,14,3,3,16, +16,8,16,11,4,3,3,11,6,1,7,4,5,11,5,4,6,4,15,15,5,3,11,15,5,5,8,8,15,16,9,15,1,14,10,4,3,2,11,11,1,3,5,16,13,15,5,4,1,0, +0,12,6,2,12,12,1,13,1,16,16,10,5,12,6,4,13,1,6,2,8,12,15,6,4,6,10,2,8,6,16,2,11,14,4,14,15,15,6,13,2,2,4,15,16,2,6,4,16,1, +10,3,7,7,5,14,13,7,15,12,15,8,8,5,16,15,8,10,15,12,3,8,5,8,8,5,5,7,15,4,15,7,11,15,9,2,11,14,7,12,6,1,7,2,15,4,16,14,4,0, +0,16,4,9,14,12,13,8,13,3,10,9,8,3,1,2,9,10,12,10,7,7,3,7,12,9,15,1,2,16,12,1,3,13,3,14,9,1,15,3,1,12,11,8,5,1,5,8,2,2, +14,9,13,8,12,1,8,1,1,10,10,1,10,1,15,11,1,12,2,14,1,5,12,8,2,16,4,8,10,2,1,8,16,14,7,4,6,6,9,2,15,9,8,12,12,5,5,6,11,0, +0,4,2,12,14,2,13,6,12,2,2,4,3,8,2,4,5,14,1,10,7,1,8,14,5,4,5,12,15,13,9,6,10,8,10,1,12,4,4,7,5,6,6,6,4,7,4,2,2,3, +16,14,8,1,1,6,5,7,7,2,1,6,11,8,14,4,13,16,3,12,12,6,11,10,11,5,1,11,14,15,3,16,14,4,2,14,4,11,1,9,13,9,6,12,8,9,10,15,6,0, +0,15,5,8,15,3,16,12,4,14,8,11,3,4,4,5,7,16,4,3,4,6,16,4,6,2,7,16,1,10,5,9,4,11,9,9,3,10,14,2,14,6,7,15,10,6,14,2,8,10, +8,1,13,10,3,12,16,9,15,1,10,15,7,12,10,2,11,14,5,16,7,15,7,11,7,15,3,15,3,1,16,11,5,3,15,6,1,6,5,14,16,3,15,7,1,10,16,11,10,0, +0,9,7,12,16,2,8,4,13,9,8,5,14,16,1,16,2,5,6,2,2,4,6,3,5,5,16,12,15,13,13,13,15,11,2,7,1,13,3,4,15,14,13,13,12,3,13,6,12,16, +15,15,14,14,11,11,14,2,3,11,14,16,9,11,11,10,6,2,12,14,16,3,6,2,7,10,4,8,6,14,15,13,16,16,8,7,7,13,13,8,3,12,4,11,8,12,15,7,7,0, +0,16,8,1,10,8,1,10,2,4,11,3,3,1,16,11,2,13,13,14,2,6,12,11,7,10,12,16,7,8,8,14,7,15,15,2,12,16,15,15,13,12,6,4,1,2,4,4,15,5, +15,7,7,15,1,1,14,3,9,6,8,7,1,3,8,7,5,4,16,14,11,3,15,6,12,7,3,5,13,10,8,2,2,15,11,3,12,11,4,10,13,16,12,9,5,16,10,16,1,0, +0,6,5,2,1,5,3,10,8,12,8,13,1,6,16,11,16,7,12,6,16,2,16,8,2,4,7,12,7,10,13,4,10,8,6,5,7,6,9,11,14,1,1,2,6,9,15,15,9,4, +5,5,10,8,3,13,15,14,6,5,11,3,13,11,12,12,8,14,5,4,11,1,11,6,14,8,6,16,7,11,16,2,3,4,5,15,15,15,3,14,12,10,13,6,11,8,7,1,3,0, +0,1,16,13,16,4,6,12,12,4,9,15,14,13,13,7,6,4,16,11,15,6,6,15,9,8,13,10,13,9,11,1,16,15,15,12,10,8,16,16,1,13,14,9,15,14,1,11,10,2, +10,13,11,1,2,2,16,15,7,7,15,16,6,10,2,9,3,2,5,3,5,12,14,13,14,11,7,15,2,10,1,5,15,8,5,4,8,12,1,4,7,4,10,7,12,3,11,5,14,0, +0,3,6,7,11,13,5,1,16,7,10,15,14,6,16,11,1,11,2,11,3,3,6,5,7,9,1,7,15,2,1,15,8,2,2,6,14,8,13,1,7,1,7,4,6,3,2,12,11,6, +9,6,2,9,2,12,2,14,16,9,3,12,9,4,15,7,13,14,12,13,7,2,11,8,13,7,7,10,14,13,4,2,6,16,2,7,8,4,12,14,5,11,6,2,7,14,15,13,2,0, +0,2,8,13,4,7,1,16,14,12,1,16,2,3,9,5,2,12,13,8,2,8,15,3,3,8,4,16,12,14,16,8,15,14,7,7,2,11,15,9,11,7,13,8,15,7,8,1,6,16, +13,3,5,7,15,4,7,13,11,14,15,3,14,5,11,3,4,11,5,8,9,2,10,8,6,8,16,10,3,11,1,4,7,7,16,8,6,7,4,9,5,4,13,6,5,5,15,16,7,0, +0,14,5,12,14,12,11,9,11,6,1,2,8,6,3,11,3,9,2,12,14,2,3,1,2,6,15,11,10,1,6,14,7,3,9,6,13,15,15,16,5,14,5,14,15,13,10,9,12,13, +7,3,7,16,15,4,16,3,4,2,1,13,12,6,9,8,16,10,11,1,11,14,10,7,12,2,15,11,2,8,2,3,16,5,16,4,12,3,7,8,14,11,8,10,15,10,8,9,13,0, +0,10,9,10,8,13,10,11,1,1,11,15,11,15,3,13,14,8,14,3,13,7,3,7,3,14,16,7,2,8,14,12,6,10,12,5,3,15,2,10,5,12,1,13,2,15,3,7,7,12, +14,16,15,1,8,8,7,9,3,9,5,9,16,12,13,7,6,1,11,10,3,11,15,6,11,9,1,16,9,10,15,7,15,10,13,14,4,7,7,1,6,7,15,1,12,7,11,5,15,0, +0,10,7,7,11,9,8,2,8,10,13,2,9,8,13,1,12,9,13,4,12,16,13,12,15,15,10,8,8,2,15,2,9,1,1,3,13,3,4,13,13,8,5,1,14,1,2,12,3,8, +16,16,9,4,4,5,16,5,1,9,6,6,7,3,9,15,16,15,16,4,16,9,12,5,6,2,10,10,12,10,16,7,7,10,1,9,4,4,8,9,13,6,12,11,6,10,12,11,13,0, +0,5,3,12,16,8,15,7,9,9,13,7,11,16,11,2,11,4,6,1,16,14,14,11,16,6,15,10,2,6,11,8,14,8,16,14,12,4,16,8,5,7,11,15,1,12,2,15,11,14, +2,15,11,5,12,16,5,15,16,9,7,8,2,6,13,15,6,5,1,16,12,1,13,5,7,4,8,6,3,5,8,12,14,12,1,13,5,15,6,13,16,16,9,15,9,2,9,4,7,0, +0,9,13,4,1,5,15,1,2,8,12,11,14,11,5,14,15,12,13,9,4,13,14,16,16,4,6,14,12,14,8,14,4,9,10,3,9,9,7,4,1,7,15,10,5,1,6,7,5,8, +4,6,5,6,1,9,5,11,12,7,10,2,6,8,6,15,4,8,16,4,14,4,14,10,12,12,13,8,10,3,9,12,7,14,3,3,4,4,11,14,4,16,7,16,13,14,14,16,8,0, +0,10,5,13,15,9,3,4,5,7,4,6,16,14,5,14,5,1,6,6,5,12,4,12,5,2,3,8,8,16,14,12,5,10,12,15,14,14,9,4,11,1,11,4,1,2,1,3,8,8, +12,10,16,15,8,7,16,2,6,7,1,3,16,15,10,12,4,11,3,10,10,12,16,4,15,12,8,5,6,9,11,15,9,9,13,11,8,9,11,9,11,10,5,15,15,6,6,8,7,0, +0,14,6,10,12,2,5,7,8,12,8,10,13,1,3,13,15,3,10,8,14,14,11,14,7,14,2,15,5,8,7,10,12,16,13,7,16,6,6,12,16,6,14,12,7,9,1,6,13,3, +1,3,11,16,5,7,8,5,3,10,2,7,9,2,12,9,14,1,4,9,5,16,16,16,10,5,3,15,5,1,9,5,7,13,10,7,13,14,6,10,14,4,9,9,9,9,11,12,13,0, +0,1,1,12,9,9,5,4,12,10,9,14,4,7,10,6,12,2,5,5,3,16,7,8,7,3,14,11,5,16,9,11,12,12,7,4,12,12,8,4,3,7,10,10,4,2,15,3,13,5, +2,13,10,10,11,3,14,5,4,4,4,10,14,13,12,13,5,9,1,16,7,2,1,4,14,1,5,10,3,12,5,15,15,9,8,16,7,11,4,8,15,6,14,16,13,10,6,2,16,0, +0,2,11,13,7,15,6,12,5,7,13,11,10,7,9,4,15,1,7,1,5,12,8,3,14,2,2,16,2,3,15,16,15,1,15,2,6,6,4,8,11,15,7,10,10,12,5,3,1,3, +7,5,3,9,14,3,16,15,13,14,9,8,6,16,10,2,13,9,15,13,8,10,9,12,1,6,10,2,2,4,6,9,10,13,6,9,10,11,2,15,5,12,7,11,15,1,4,13,2,0, +0,12,11,1,12,4,11,16,8,1,14,15,3,4,9,10,5,4,9,5,14,1,16,13,6,4,13,8,16,15,5,1,4,12,6,1,6,13,6,5,16,13,5,5,5,16,10,16,1,1, +5,9,13,16,7,12,12,10,3,3,1,2,14,4,5,10,5,12,7,9,12,13,15,13,11,16,9,10,4,4,9,11,12,1,7,2,16,3,6,7,5,13,10,8,4,9,3,10,14,0, +0,3,7,1,7,8,8,10,10,15,16,11,9,13,8,4,3,15,6,2,2,3,8,1,14,16,14,5,11,12,16,3,8,7,6,10,2,15,2,5,3,15,4,15,16,14,8,11,12,15, +10,9,4,7,7,13,11,8,14,8,13,14,14,4,8,9,1,8,2,5,9,4,11,7,6,3,1,16,16,11,8,10,11,12,1,11,5,16,9,3,6,13,3,11,1,1,16,9,3,0, +0,16,3,10,14,6,9,3,11,11,13,16,1,1,14,5,9,9,13,4,11,5,11,14,15,9,8,8,16,9,7,5,7,7,8,9,15,9,15,9,2,4,16,11,12,13,13,3,8,10, +4,1,6,8,4,14,12,7,11,10,16,12,8,6,7,5,7,14,6,15,2,16,15,7,3,7,153,7,2,13,14,7,6,8,2,14,3,16,8,3,13,11,13,11,6,10,8,6,13,0, +0,16,1,7,3,10,7,4,1,1,6,14,6,12,4,15,2,4,9,1,7,8,4,6,153,153,149,150,2,2,3,16,5,12,10,13,11,8,9,12,15,11,4,4,14,15,4,2,12,1, +8,2,8,11,10,2,11,4,9,3,15,8,11,7,11,2,6,6,8,3,6,8,153,149,165,165,189,150,8,6,3,13,11,15,14,5,4,8,13,7,9,6,7,1,5,16,6,5,2,0, +0,4,1,15,5,8,2,15,1,13,1,6,11,12,15,16,15,6,6,3,4,4,149,165,181,167,167,188,150,14,9,2,9,7,7,6,15,1,11,12,15,13,1,14,3,10,14,10,11,12, +2,15,5,7,6,4,14,12,11,15,3,2,8,10,6,7,10,8,15,15,4,149,179,151,155,155,152,183,150,6,4,16,15,6,12,13,4,13,6,3,6,4,1,13,15,8,4,12,1,0, +0,11,4,9,16,4,1,11,3,9,6,13,12,1,16,10,5,12,10,10,9,149,180,151,11,2,7,152,184,150,14,5,2,1,11,9,16,10,9,1,15,6,13,2,3,13,9,9,13,6, +7,10,7,14,4,2,8,6,9,14,5,3,11,4,8,9,10,4,4,5,149,188,151,13,12,4,15,152,189,150,11,6,11,13,10,10,7,7,6,1,7,5,2,7,1,1,11,3,10,0, +0,3,7,9,16,10,13,13,8,13,11,11,5,16,8,15,14,9,11,8,149,177,151,3,6,1,3,14,152,179,150,8,16,9,8,1,3,10,9,9,7,11,6,15,6,2,10,5,12,10, +2,4,5,12,12,10,2,5,12,12,4,10,2,3,11,10,15,2,4,156,183,166,13,8,16,6,2,8,152,183,150,10,7,13,1,2,15,9,11,6,7,9,14,8,5,8,14,10,11,0, +0,7,4,16,6,2,5,3,5,1,14,14,8,6,4,14,6,8,16,2,168,180,154,16,4,13,3,1,8,168,182,150,15,12,12,7,7,1,12,5,2,6,6,8,5,14,4,16,12,5, +4,2,4,14,8,8,4,6,9,7,8,4,5,15,7,9,11,2,8,156,188,151,7,10,15,12,1,3,156,179,184,150,1,7,9,12,7,4,16,9,7,12,16,8,2,3,6,15,12,0, +0,5,2,7,10,5,1,8,4,4,16,2,12,8,1,6,7,14,14,15,168,151,9,15,12,5,15,3,12,148,184,181,150,6,16,14,16,7,13,5,13,3,6,2,7,3,2,12,7,8, +12,6,14,15,2,6,14,14,10,9,11,13,14,2,3,9,2,10,12,149,151,2,16,5,14,15,2,16,10,148,181,182,150,4,8,14,10,11,1,3,9,1,1,16,10,16,12,7,3,0, +0,10,1,11,15,5,13,6,13,10,14,7,2,4,13,6,12,10,15,149,166,16,4,6,5,7,11,7,16,12,148,189,180,150,3,5,6,4,14,14,7,14,14,6,1,9,15,8,4,14, +5,8,1,1,1,11,8,15,4,11,13,16,12,10,11,12,4,6,156,184,154,6,3,8,4,14,8,14,4,8,148,182,189,150,1,16,13,16,15,1,12,11,11,10,12,5,5,9,10,0, +0,4,10,3,4,3,6,1,15,15,13,12,15,3,3,16,14,13,9,152,166,9,2,6,4,4,2,2,2,12,12,148,180,179,150,3,16,11,1,5,10,1,7,2,8,16,11,9,7,8, +14,4,7,13,13,11,16,2,3,1,8,15,7,6,12,6,14,9,11,168,154,8,14,7,7,16,1,9,12,11,12,148,177,179,158,4,7,13,2,13,7,3,7,4,8,8,6,15,4,0, +0,5,1,11,2,5,11,13,5,9,1,6,7,3,12,9,13,8,9,156,166,4,9,3,2,5,4,9,15,15,3,5,168,178,166,2,6,5,2,16,8,14,14,16,15,11,6,12,4,8, +1,5,14,15,4,13,5,15,3,13,1,10,5,4,11,9,6,5,1,168,154,1,20,15,12,2,11,4,4,15,4,156,189,188,154,13,4,15,13,12,15,16,1,16,11,12,11,4,7,0, +0,3,2,6,12,14,2,11,14,5,8,5,12,14,10,13,9,9,7,149,166,13,9,17,7,11,14,12,8,11,16,8,164,180,166,9,11,1,10,15,16,2,14,14,9,14,7,6,11,8, +11,12,16,9,13,13,9,8,3,1,4,11,1,6,15,3,2,3,156,185,154,4,4,17,5,12,13,12,13,5,4,145,180,179,154,13,16,1,3,16,7,8,13,3,1,7,12,12,11,0, +0,16,16,4,6,4,1,11,11,5,11,14,6,9,4,10,12,1,15,152,166,11,10,4,18,27,2,8,7,14,15,156,189,177,166,2,4,13,8,9,6,14,3,5,1,13,2,7,12,15, +7,11,3,7,1,7,13,1,3,1,9,7,8,14,8,11,7,14,6,168,146,8,9,4,17,32,2,1,11,10,11,164,181,181,154,9,15,15,14,10,9,15,2,10,13,15,13,14,8,0, +0,10,3,10,5,2,1,10,16,10,5,6,1,9,1,13,7,7,5,156,187,150,5,10,30,17,2,1,3,7,15,156,181,178,166,4,1,8,8,5,1,3,13,7,15,14,3,16,14,4, +16,10,14,12,2,6,13,13,7,13,2,16,14,13,12,11,9,4,11,168,189,150,13,16,18,17,15,15,13,12,13,164,182,184,154,8,9,8,12,16,13,13,13,5,11,16,6,2,10,0, +0,9,16,4,5,2,5,3,4,12,5,13,4,13,1,2,8,15,13,156,180,189,150,6,13,17,17,11,12,6,2,156,188,183,166,5,10,13,2,12,2,10,1,12,1,14,6,11,16,7, +4,15,15,8,8,16,15,14,2,14,5,12,11,13,2,7,13,1,10,152,188,186,150,16,2,29,25,1,7,8,2,164,184,187,154,5,13,14,1,10,14,12,8,14,8,10,12,7,10,0, +0,4,7,16,12,3,4,13,15,5,12,15,7,8,15,14,8,15,8,11,168,182,184,150,1,6,2,12,12,10,16,149,178,185,151,1,15,2,1,7,12,13,4,1,15,9,4,12,15,15, +8,8,2,4,5,16,8,7,2,5,16,13,2,7,16,4,11,13,1,156,184,179,189,150,5,16,15,9,5,12,156,179,178,166,1,8,16,9,6,10,1,15,3,2,3,15,15,15,16,0, +0,12,6,11,14,7,9,5,4,16,1,8,3,9,6,6,10,3,12,14,148,178,179,179,194,5,1,14,11,12,8,164,186,179,154,4,13,14,16,16,3,3,5,1,6,4,13,12,8,7, +3,1,11,1,11,12,2,8,12,3,4,1,5,1,12,11,13,8,16,15,148,179,185,206,150,13,1,3,13,8,149,186,189,151,3,13,13,7,10,8,2,7,8,4,3,8,11,6,13,0, +0,15,6,11,8,9,13,12,11,6,9,16,16,10,13,13,3,12,14,10,2,148,184,208,189,150,12,15,8,1,156,178,178,151,1,1,3,3,10,2,13,15,5,6,11,5,12,7,12,15, +16,4,5,14,7,8,13,15,13,6,5,2,4,1,4,8,10,9,2,1,12,148,206,180,180,150,9,2,4,14,164,177,151,1,12,7,9,14,8,5,14,12,7,6,1,16,5,15,4,0, +0,7,15,16,6,2,5,15,1,15,4,12,7,11,10,6,15,8,7,3,6,13,196,180,186,188,150,12,3,3,156,186,151,7,4,6,6,13,12,1,1,16,3,9,16,4,11,1,13,15, +14,5,2,5,9,11,11,13,3,11,12,3,9,16,2,13,9,8,11,1,3,16,152,179,181,186,150,7,8,14,164,151,15,14,5,10,13,6,1,13,14,2,3,3,3,15,10,2,13,0, +0,3,3,10,5,5,6,2,9,13,10,2,3,16,11,6,12,11,15,13,6,5,5,148,178,177,189,150,153,153,149,151,14,5,10,5,10,15,13,7,16,5,7,11,5,16,10,13,7,2, +1,15,7,8,16,14,3,8,2,10,10,4,7,7,7,5,8,2,14,9,3,12,9,148,178,189,180,165,165,161,151,12,15,7,14,1,2,1,7,4,7,4,5,10,4,11,7,15,4,0, +0,16,5,16,2,8,12,4,3,14,1,8,8,8,4,11,14,7,15,2,14,11,10,4,148,183,187,184,185,189,151,8,9,13,1,2,11,13,1,6,2,5,3,8,2,14,8,6,11,15, +6,12,12,5,14,8,16,3,5,9,14,7,15,3,14,2,8,4,2,14,9,5,8,3,148,182,184,178,177,151,4,15,11,8,8,7,14,15,12,7,15,14,2,11,4,14,5,5,15,0, +0,12,6,4,6,16,7,16,13,2,10,11,14,13,11,6,5,9,6,5,13,1,6,8,4,148,179,179,167,151,12,9,16,11,12,14,1,1,8,7,6,13,15,7,16,11,15,6,14,10, +13,14,14,10,3,13,15,6,2,4,9,2,15,12,16,15,12,12,5,10,7,10,5,2,15,148,163,151,159,14,1,2,11,8,4,13,5,7,1,8,7,10,1,9,8,13,9,4,15,0, +0,16,9,16,1,13,16,13,4,4,4,11,11,13,1,14,6,8,10,16,9,7,4,14,12,2,159,155,11,5,11,7,10,1,11,4,12,10,2,14,14,10,12,10,13,15,12,16,13,11, +9,10,13,8,14,7,8,11,12,5,14,16,7,9,10,13,4,12,14,11,13,8,9,8,11,12,16,2,12,7,9,10,15,12,15,4,8,15,11,6,11,9,13,8,15,2,4,6,13,0, +0,14,15,14,2,7,7,12,15,14,15,8,8,5,4,15,15,6,15,10,16,5,13,6,13,12,8,13,4,2,15,15,8,1,11,4,7,15,13,14,6,11,16,7,4,9,5,2,6,10, +9,9,3,14,8,15,1,2,8,1,15,11,15,10,8,2,8,16,10,5,8,13,12,10,7,1,11,14,5,4,9,3,8,4,16,2,14,6,16,12,9,5,16,6,4,1,13,14,15,0, +0,12,7,3,13,12,4,9,15,2,14,9,13,9,12,13,8,10,5,11,10,9,9,6,11,8,8,14,16,3,11,15,10,5,10,16,6,5,9,6,15,6,7,3,10,6,2,5,10,3, +1,10,14,13,15,6,3,12,6,14,6,5,3,3,1,12,12,1,9,4,4,13,11,9,7,10,2,15,10,1,1,7,16,9,7,13,4,1,13,6,11,6,6,2,7,11,15,12,3,0, +0,14,12,8,1,12,3,16,6,15,8,7,4,6,3,14,11,3,9,4,9,6,2,12,14,1,6,7,10,8,13,8,13,11,16,2,10,16,9,8,1,8,1,15,4,10,3,11,6,8, +5,9,1,6,14,16,10,3,3,3,15,8,11,6,15,8,15,10,12,4,7,16,2,11,6,6,15,11,1,10,12,1,10,8,3,8,1,10,13,10,6,9,15,15,6,12,16,12,14,0, +0,9,16,6,4,5,3,12,8,15,16,14,13,16,7,8,16,7,15,12,15,7,2,14,16,9,15,9,12,7,8,11,16,3,6,6,14,3,5,2,13,14,5,12,7,5,13,3,13,9, +15,16,16,9,4,9,13,13,13,2,11,16,8,16,10,15,6,12,12,13,12,16,7,13,1,9,2,6,12,7,8,1,10,12,5,8,8,12,8,9,8,14,3,6,11,13,10,16,7,0, +0,10,9,2,7,2,14,13,7,2,10,7,10,15,16,7,2,2,13,14,5,1,6,4,4,9,6,9,10,14,4,9,6,15,13,4,4,2,8,5,7,5,3,15,8,1,7,15,13,4, +3,9,6,12,10,4,7,5,5,15,8,3,5,3,2,4,12,2,5,13,8,1,9,6,9,16,9,2,9,1,11,7,6,16,7,3,6,14,16,11,4,2,12,9,4,10,9,16,14,0, +0,7,5,8,9,15,1,7,1,16,15,14,1,16,6,10,15,16,9,1,10,15,8,10,3,10,15,6,2,6,8,3,16,9,7,11,15,3,14,6,1,1,12,6,1,14,11,11,9,15, +10,6,11,9,14,1,15,1,10,11,12,6,7,8,2,7,12,6,12,15,6,13,13,3,16,14,4,3,14,7,11,10,15,15,7,11,12,8,5,6,8,14,14,4,2,8,7,10,4,0, +0,13,9,8,1,6,14,14,6,14,8,2,9,1,13,6,16,11,2,16,16,8,13,3,16,5,7,5,7,16,6,11,14,6,2,11,13,5,4,12,12,13,5,6,4,13,14,15,15,5, +15,2,5,13,6,6,14,16,6,10,4,5,2,16,11,3,15,9,5,4,13,2,2,13,12,11,1,3,10,13,16,8,4,5,11,15,5,11,12,8,7,6,12,1,3,12,4,8,14,0, +0,11,13,12,6,14,8,7,7,5,9,4,16,13,8,12,12,11,4,12,12,4,15,5,3,5,16,13,11,14,2,15,2,4,5,10,10,16,15,2,10,16,6,14,12,6,9,11,16,9, +6,9,9,15,12,6,14,4,1,13,13,2,4,6,14,2,5,15,12,2,8,5,2,1,4,8,1,16,1,13,9,6,10,8,16,7,12,2,12,15,7,5,7,8,15,15,12,2,8,0, +0,10,6,2,13,6,12,4,13,4,6,16,7,15,1,12,14,5,1,3,10,2,3,12,12,6,15,5,16,12,3,5,8,8,5,10,15,4,6,13,10,4,12,13,4,6,10,4,2,13, +6,13,8,9,3,10,2,2,7,11,11,4,15,10,1,5,11,10,8,1,4,2,13,11,8,15,1,12,13,7,12,5,13,6,14,12,12,12,11,14,2,1,16,14,13,6,14,7,4,0, +0,10,16,15,6,2,2,16,5,5,10,1,14,8,15,5,1,11,8,9,8,10,7,10,12,16,9,14,3,2,11,9,12,2,3,13,6,16,5,5,11,5,2,13,2,11,6,10,14,6, +8,2,2,3,9,11,10,16,6,7,15,14,12,1,10,11,16,10,15,14,5,15,13,12,4,10,11,16,4,13,12,3,6,4,16,7,4,7,12,9,3,8,5,16,4,4,8,13,1,0, +0,13,4,1,1,14,15,1,8,11,13,10,3,1,7,6,1,9,5,16,4,15,2,5,15,16,7,16,4,7,14,14,4,3,4,12,5,15,3,9,9,10,8,2,5,3,16,6,14,9, +15,6,10,12,15,16,2,1,13,5,3,10,14,11,6,12,1,4,4,8,7,2,4,16,14,6,13,2,3,13,1,12,2,5,4,11,5,9,7,10,3,3,9,1,4,12,9,8,13,0, +0,11,15,15,2,1,14,16,2,7,3,9,12,5,3,5,2,5,6,15,7,6,13,11,3,13,10,14,5,1,5,2,14,16,9,7,5,11,7,16,3,8,4,7,8,1,10,6,9,6, +5,14,9,5,11,4,2,3,13,10,2,1,15,16,14,8,6,11,12,5,8,15,3,9,15,4,16,3,7,7,15,8,15,4,16,15,9,10,6,1,7,13,5,9,1,1,6,5,14,0, +0,7,14,12,4,10,1,5,12,7,5,10,2,16,6,1,13,1,5,10,10,10,13,9,1,7,1,16,16,12,14,5,1,4,6,9,3,5,6,5,15,11,5,9,7,11,15,1,4,5, +15,1,11,4,10,9,9,4,7,3,16,10,3,14,5,10,15,16,6,12,6,5,8,16,4,16,4,11,2,10,12,11,10,4,8,3,15,3,4,12,11,5,7,6,13,12,10,8,12,0, +0,3,2,1,8,3,6,9,12,6,5,9,8,4,13,12,10,14,10,12,12,4,5,13,3,1,1,2,4,12,1,9,12,12,16,12,9,15,11,2,2,5,6,16,12,6,6,5,8,9, +3,13,11,1,5,7,10,1,16,9,3,9,5,6,13,8,16,9,9,8,7,10,3,13,12,10,1,7,10,7,4,14,7,5,7,7,4,7,15,16,11,7,14,1,3,13,14,15,11,0, +0,13,16,6,12,4,7,13,2,6,3,1,16,16,5,8,4,1,11,8,16,6,8,9,5,15,12,1,4,12,9,9,14,12,2,9,8,1,8,10,3,11,15,4,3,12,12,3,12,6, +13,15,5,16,14,7,12,8,3,8,9,11,3,13,16,12,2,1,5,12,1,11,10,9,2,2,14,2,5,11,2,3,7,10,1,7,6,16,8,8,11,16,1,13,1,7,5,13,16,0, +0,13,9,11,7,3,2,6,14,4,9,8,8,1,2,13,11,1,9,6,4,16,11,9,3,13,13,1,15,14,5,12,1,11,15,13,8,1,13,13,6,4,4,7,2,9,13,12,10,11, +3,16,2,9,14,5,9,15,8,13,12,10,12,3,14,9,5,7,4,13,2,9,7,6,4,14,1,12,1,13,16,4,12,13,2,11,1,12,11,12,9,6,14,6,3,12,2,11,15,0, +0,10,9,15,10,14,9,12,1,15,8,11,3,10,3,8,15,9,12,7,11,10,15,2,8,5,16,16,16,11,12,12,1,5,9,12,7,6,4,15,4,6,3,9,1,10,6,11,2,11, +5,8,7,16,12,6,8,10,2,6,13,13,7,15,10,10,2,15,9,13,16,11,10,6,4,16,4,10,11,15,6,8,3,16,2,3,5,2,4,5,15,12,13,16,4,8,4,10,16,0, +0,15,2,10,4,4,1,14,3,16,8,4,11,15,15,9,10,9,12,2,12,4,1,2,11,2,14,10,11,15,12,7,13,7,5,16,16,1,11,11,13,1,1,10,13,6,2,11,2,13, +3,15,5,13,7,6,12,8,8,11,4,5,16,12,5,8,6,4,3,1,10,8,10,10,6,7,3,8,15,11,16,10,6,8,14,9,3,12,3,9,13,2,3,9,1,13,9,1,10,0, +0,12,14,16,16,9,9,8,3,11,13,8,13,5,5,5,1,14,12,6,2,11,15,15,5,2,10,8,14,10,9,8,3,10,11,5,8,9,12,8,4,1,12,10,14,10,9,3,13,13, +15,12,13,5,4,6,2,1,13,16,6,10,7,2,11,7,12,14,5,11,6,9,3,8,11,2,5,14,3,11,7,12,2,1,6,16,11,2,12,6,15,7,2,9,16,12,16,1,11,0, +0,2,12,2,4,2,10,11,8,6,11,1,12,16,10,11,4,7,5,1,9,7,13,1,7,15,12,14,16,5,12,15,9,2,13,14,15,3,5,12,14,11,13,14,12,15,2,12,16,12, +6,5,6,3,6,10,10,3,13,1,4,15,15,7,11,12,5,8,9,2,8,8,8,11,6,9,8,4,15,2,8,13,3,10,13,7,8,14,11,7,4,10,11,2,2,15,8,4,12,0, +0,6,9,10,6,15,8,6,10,14,16,14,11,2,3,3,4,3,7,4,11,4,15,5,12,12,3,4,14,13,5,6,15,3,16,10,4,15,7,8,14,13,5,15,4,1,14,6,7,7, +13,3,14,5,11,16,9,5,13,8,16,13,13,16,7,3,9,3,9,7,8,3,7,12,6,8,9,15,7,16,13,1,3,1,8,11,11,6,6,11,5,1,6,6,14,11,3,10,9,0, +0,1,7,9,1,11,13,8,15,13,4,14,11,14,1,10,11,1,11,3,16,5,15,16,10,6,12,1,4,11,11,6,5,10,2,10,1,3,3,3,9,5,12,7,9,9,9,5,12,7, +5,11,8,1,14,16,9,5,16,10,14,9,6,10,4,10,1,11,4,4,1,4,16,8,12,6,6,5,6,12,15,5,13,13,12,9,7,7,11,16,8,7,3,1,11,2,6,16,8,0, +0,11,8,15,15,2,14,4,12,16,15,1,8,5,7,14,12,2,15,3,5,8,2,9,13,7,12,9,15,3,9,15,8,12,5,4,6,7,13,4,4,6,16,10,1,13,10,2,11,1, +5,3,11,8,6,12,6,6,12,16,13,10,16,6,6,1,7,15,6,4,4,14,15,12,9,1,4,1,8,7,4,8,15,14,13,4,13,1,14,10,14,9,16,10,12,15,15,3,1,0, +0,16,3,5,10,12,16,9,16,10,10,2,16,2,2,2,16,15,14,15,7,16,11,1,4,10,6,8,6,6,4,7,6,16,14,4,12,11,16,13,9,13,12,2,16,1,7,8,9,6, +13,16,16,4,8,1,11,6,6,3,15,11,11,5,10,2,15,10,13,1,12,7,10,12,14,2,9,12,6,5,16,12,3,13,11,10,10,7,8,5,3,6,5,16,5,14,6,16,12,0, +0,8,14,11,8,12,15,14,13,2,13,1,4,16,16,4,11,3,10,3,6,1,5,14,5,8,4,2,14,15,2,16,16,6,2,4,4,4,16,3,9,10,1,9,8,1,2,12,3,10, +9,12,4,3,14,16,2,5,1,14,9,3,6,10,2,12,9,2,12,9,14,6,13,6,13,16,1,7,6,14,11,8,15,8,5,8,5,8,14,16,10,1,13,12,9,14,15,3,1,0, +0,3,13,14,11,4,2,5,1,3,2,8,8,6,6,10,13,12,4,8,14,4,13,15,4,8,2,8,2,13,14,5,12,6,8,9,15,4,5,2,6,16,7,8,8,5,9,3,8,7, +15,4,5,16,15,6,4,8,1,7,6,3,14,14,16,14,13,12,6,14,12,14,3,5,5,9,16,15,12,15,13,3,1,11,7,16,13,3,4,2,3,8,6,16,2,5,8,8,3,0, +0,11,3,9,5,15,16,11,11,5,8,4,14,11,7,2,3,1,10,7,16,7,16,1,10,12,8,2,10,4,16,10,6,13,9,13,6,12,1,11,2,2,11,8,4,2,6,7,5,15, +6,12,9,11,13,4,11,16,8,16,4,3,13,7,16,10,14,14,11,10,16,10,14,5,2,13,2,15,3,8,12,6,3,10,3,10,13,2,10,8,12,13,3,13,10,4,14,1,14,0, +0,4,4,12,4,12,8,12,16,2,9,14,4,3,5,3,8,4,15,16,9,12,13,16,7,7,12,2,10,7,12,8,10,1,16,11,8,14,2,6,5,13,16,9,10,2,11,11,4,3, +12,12,6,11,13,13,3,6,4,13,4,12,8,3,2,12,6,10,10,11,10,13,10,14,6,12,5,12,11,7,13,1,15,3,10,9,10,6,3,4,5,9,6,4,14,6,16,13,3,0, +0,3,6,9,12,12,7,1,9,5,14,10,13,13,16,5,11,10,12,14,14,10,9,8,8,7,7,14,7,15,14,5,14,12,14,10,10,14,2,2,16,14,10,11,16,16,1,11,14,13, +10,4,16,16,4,6,3,9,15,13,10,16,1,3,6,4,8,8,16,7,7,4,5,4,6,2,11,12,8,7,13,5,2,14,13,13,1,8,3,8,10,11,15,1,6,5,6,10,6,0, +0,2,2,14,4,11,15,6,9,1,8,16,16,13,11,9,5,1,4,10,4,11,13,8,3,10,10,7,5,3,12,4,10,14,3,11,15,10,8,4,13,7,2,2,8,14,6,7,3,7, +6,8,5,16,8,16,14,4,14,7,4,4,8,11,13,14,2,8,7,10,15,3,14,12,15,14,5,1,12,1,13,16,12,4,14,12,12,4,14,3,6,13,11,10,15,3,14,5,4,0, +0,8,16,7,13,7,5,9,14,4,10,13,12,2,4,16,11,3,8,12,16,11,11,12,16,13,2,12,3,14,4,9,13,1,7,14,6,11,3,11,6,4,16,12,5,16,6,16,11,6, +15,6,12,7,5,16,7,1,1,11,9,7,11,5,11,15,10,10,2,10,1,3,3,12,6,12,15,4,9,10,9,1,12,5,15,2,13,1,2,1,11,1,12,9,16,7,10,4,9,0, +0,8,2,2,3,15,9,1,2,13,11,7,12,13,5,12,3,14,11,7,9,5,4,7,10,11,11,15,3,11,1,6,6,7,10,9,10,7,15,7,10,3,14,5,7,12,9,12,5,4, +6,11,3,15,10,8,6,12,13,4,1,14,1,16,13,10,7,3,6,5,6,5,11,10,5,16,13,4,14,16,16,2,15,6,9,3,6,3,1,12,5,11,4,1,1,6,14,12,16,0, +0,9,1,3,6,12,12,3,4,12,8,13,11,4,13,6,7,7,9,16,13,1,6,3,8,7,4,15,14,7,12,15,12,6,16,3,9,2,12,7,2,1,16,13,15,4,9,1,16,1, +6,13,8,1,7,7,6,3,3,6,10,16,5,14,2,4,15,8,1,6,7,2,4,14,12,4,12,14,3,8,1,15,8,3,1,14,12,14,2,16,8,9,16,16,11,10,12,15,9,0, +0,13,9,7,15,1,3,4,15,1,4,1,6,10,5,11,5,5,12,7,9,7,13,11,10,3,7,5,13,7,4,4,6,14,14,16,1,15,9,16,11,16,6,5,11,16,4,14,4,13, +9,12,6,1,12,6,9,8,2,1,3,12,4,11,10,1,8,13,16,4,10,10,1,14,5,16,2,1,13,7,6,12,15,3,7,6,3,15,11,2,14,5,3,13,13,6,9,14,7,0, +0,4,6,3,14,13,9,10,1,3,8,12,16,15,3,3,2,10,11,8,1,15,14,6,5,8,15,8,7,1,15,10,15,5,15,7,10,1,1,12,1,1,10,6,15,3,11,2,15,5, +4,9,16,9,15,3,7,5,14,10,6,12,2,6,4,5,6,12,4,6,6,4,11,4,13,16,8,1,4,2,12,16,1,12,6,16,10,13,3,16,3,3,13,13,16,9,15,3,16,0, +0,16,12,16,15,14,7,11,4,2,12,2,4,6,13,3,11,11,1,16,11,5,4,16,8,12,5,12,13,14,8,6,8,12,7,16,12,12,14,4,1,8,15,13,3,1,1,13,3,10, +11,8,1,12,16,2,9,14,9,10,8,5,16,4,10,11,4,5,16,15,7,4,12,1,12,10,2,6,9,5,10,3,6,4,14,15,14,9,9,7,14,6,10,7,8,4,3,16,12,0, +0,7,6,13,11,9,10,13,14,15,10,3,6,4,4,16,14,14,12,13,5,10,16,12,5,14,5,7,1,7,9,16,3,13,5,2,15,15,7,1,16,5,6,9,10,16,5,15,10,7, +13,2,12,3,6,10,4,13,2,8,3,14,3,11,8,8,4,9,8,3,5,13,15,16,13,11,15,4,10,12,16,12,15,14,3,10,7,9,12,7,4,8,8,4,11,15,10,7,13,0, +0,10,16,8,7,11,9,5,5,8,5,16,12,10,12,4,2,3,1,12,10,3,6,14,3,6,9,11,8,4,2,3,2,4,8,2,4,6,15,14,1,9,4,14,6,8,6,16,13,0, +0,9,10,2,12,13,4,7,9,13,12,16,11,7,1,13,6,6,8,3,5,16,4,6,16,2,16,2,6,8,3,14,5,6,13,12,1,10,11,8,13,14,3,8,3,5,4,14,0,0, +0,0,3,7,1,5,15,2,15,11,6,7,6,13,7,2,4,16,1,2,9,10,4,2,4,16,15,2,6,9,2,1,15,11,16,12,16,15,9,4,12,11,15,9,4,8,5,12,0,0, +0,0,10,9,1,14,10,3,5,2,10,16,12,11,5,13,15,15,1,9,4,3,4,13,16,9,1,3,6,1,11,4,8,12,4,7,6,6,10,15,15,13,12,2,16,11,6,0,0,0, +0,0,0,2,9,7,5,12,5,9,15,12,12,8,5,11,11,9,4,7,2,3,16,2,8,4,1,3,6,12,2,6,11,1,6,12,10,15,2,8,11,3,14,3,10,16,11,0,0,0, +0,0,0,15,14,1,7,10,1,15,10,12,16,5,3,12,8,13,10,5,11,1,8,2,11,14,10,3,13,6,14,9,11,11,6,9,14,1,6,7,3,2,4,15,11,6,0,0,0,0 + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64, +0,0,0,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,64,64,64, +0,0,0,37,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,38,64,64, +0,0,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,38,64,64, +0,0,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,38,64, +0,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,38,64, +0,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,0,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,0,0,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,0,0,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,0,0,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,0,0,0,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,0,0,0,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,94,0,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,91,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,90,0,104,92,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,0,0,0,92,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,98,92,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,0,0,0,92,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,92,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,0,0,134,92,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,0,0,125,0,0,92,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,109,125,98,0,0,99,92,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,99,92,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,101,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,101,125,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,0,0,0,0,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,50,64, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,0, +0,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42, +44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0, +0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0, +0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0, +0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0, +0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0, +0,0,0,40,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,39,0,0,0, +0,0,0,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,0,0,0,0 + + + + + + diff --git a/V3/Content/Maps/work_in_progress.tmx b/V3/Content/Maps/work_in_progress.tmx new file mode 100644 index 0000000..d521185 --- /dev/null +++ b/V3/Content/Maps/work_in_progress.tmx @@ -0,0 +1,1258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +177,177,177,189,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,76,76,0,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,63,63,63,63,63,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,76,76,76,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,63,63,63,63,63,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,76,76,76,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,63,63,63,63,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,177,177,151,152,177,177,177,177,177,177,76,0,1,1,1,1,1,1,1,1,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,63,63,63,63,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,177,147,155,4,152,177,177,177,177,177,76,76,0,1,1,1,1,1,1,1,76,0,0,76,76,76,76,76,76,76,76,76,76,76,76,1,1,63,63,63,0,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,147,4,4,4,152,177,177,177,177,177,76,0,1,1,1,1,1,1,1,1,76,0,76,76,0,76,76,76,76,76,76,76,76,76,1,1,1,63,63,63,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,177,147,4,4,4,4,168,177,177,177,177,76,76,76,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,63,63,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,151,4,4,4,4,149,177,177,177,177,177,76,76,76,76,1,1,1,1,1,1,1,76,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,63,63,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,166,4,4,4,4,156,177,177,177,155,148,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,1,1,63,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,154,4,4,4,4,164,177,177,154,1,148,76,76,76,1,1,1,1,1,1,1,1,1,1,1,0,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,0,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,177,177,177,177,166,4,4,4,4,145,177,177,162,1,1,155,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,0,1,1,1,1,1,1,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,177,167,177,177,177,146,4,4,4,149,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,21,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,177,167,151,164,177,177,177,150,4,4,145,177,177,155,155,1,153,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,147,159,160,177,177,177,177,150,153,149,177,177,154,1,1,149,154,1,1,1,1,1,1,1,255,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,177,147,1,1,148,177,177,177,177,165,165,177,177,162,1,1,145,166,1,1,1,1,1,1,1,250,1,1,1,1,1,1,1,76,0,76,76,76,76,76,1,1,1,1,248,260,2,253,1,1,1,1,1,1,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,147,1,1,1,155,177,177,177,177,177,177,177,177,154,1,149,177,154,1,1,1,1,1,1,1,238,255,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,2,2,1,266,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,177,147,1,1,1,1,156,0,177,177,177,177,177,177,155,1,145,177,166,157,1,1,1,1,1,1,242,1,1,254,253,1,1,1,1,76,76,76,76,76,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,21,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,147,1,1,1,1,1,159,155,152,177,177,177,177,158,1,156,177,177,161,154,1,1,1,1,1,1,246,1,256,1,266,1,1,1,1,76,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,21,21,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,177,147,1,1,1,1,1,1,1,1,152,177,177,177,162,1,1,152,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,21,21,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,147,1,1,1,1,1,1,1,1,1,168,177,177,177,154,1,1,152,177,177,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,248,260,2,253,1,1,1,1,1,1,1,21,21,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,162,1,1,1,1,1,1,1,1,1,156,177,177,177,162,1,1,1,152,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,63,1,1,266,263,1,266,1,1,1,1,1,1,1,21,21,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,154,1,1,1,1,1,1,1,1,1,168,177,177,177,154,1,153,1,155,155,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,21,1,1,1,1,1,1,1,1,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +177,151,1,1,241,242,243,1,1,1,1,149,177,177,177,162,1,156,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,21,21,1,1,1,1,1,1,1,1,21,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +151,1,1,1,245,266,247,1,1,1,149,177,177,177,177,154,1,168,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,64,1,21,1,1,1,1,1,1,1,1,21,21,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +166,153,1,1,249,267,1,1,1,1,149,177,177,177,177,151,1,156,167,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,63,1,1,21,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +165,150,1,1,237,238,1,1,1,1,152,177,177,177,162,1,1,159,168,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,21,1,1,1,1,1,1,21,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +183,183,150,1,241,255,1,242,243,1,1,168,177,177,177,146,1,1,156,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,21,1,1,1,1,1,21,21,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +183,162,1,1,245,255,1,266,247,1,149,177,177,177,177,150,1,1,159,1,1,153,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,21,1,1,1,1,21,21,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,177,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +183,183,154,1,249,250,1,267,1,1,1,177,177,177,177,192,150,1,1,1,1,149,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,21,1,1,1,21,21,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,177,177,76,76,76,76,76,76,76,76,76,76,76,76,76,76, +183,162,1,1,237,238,255,238,1,1,145,177,177,177,192,177,150,1,1,1,149,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,21,1,1,21,21,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,76,76,76,76,177,177,177,1,1,1,1,1,76,76,76,76,76,76,76,1,1,76, +183,183,154,1,241,242,1,255,1,1,149,177,177,177,177,177,177,154,1,1,156,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,177,177,177,177,1,1,1,1,76,76,1,1,76,76,76,1,1,1, +183,147,1,1,1,1,245,255,1,1,148,177,177,177,177,177,166,1,1,1,168,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,21,21,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +183,147,1,1,1,1,249,250,1,1,1,148,177,177,177,177,177,150,1,1,1,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,21,21,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +162,1,1,1,1,1,237,238,255,1,1,164,177,151,155,177,177,150,1,1,152,177,151,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,164,177,151,1,4,4,4,1,4,1,4,4,4,4,1,1,4,1, +177,150,1,1,1,1,241,242,1,1,1,149,177,151,1,160,177,192,8,1,1,152,151,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,145,177,151,1,4,4,4,4,4,4,4,4,4,4,4,4,1,1, +177,150,157,1,1,1,1,1,1,1,145,177,166,1,1,148,177,151,1,1,1,159,1,1,1,1,1,1,1,1,250,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,145,177,151,4,1,4,4,4,4,4,4,4,4,4,4,4,4,1,1, +177,177,165,158,1,1,1,1,1,1,145,177,177,146,1,1,152,162,1,1,1,1,1,1,1,1,1,1,1,1,238,255,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,149,177,166,4,1,4,4,4,4,4,4,4,4,4,4,4,4,4,1, +177,177,147,1,1,1,1,1,1,149,177,177,147,1,1,1,152,146,1,1,1,1,1,1,1,1,1,1,1,1,242,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1, +177,177,162,1,1,1,1,1,1,149,177,177,162,1,1,1,157,168,146,1,1,1,1,1,1,1,1,1,1,1,246,1,256,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1, +177,177,154,1,1,1,157,1,1,177,177,177,146,1,1,160,165,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,63,76,76,76,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,148,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,162,153,1,1,149,146,1,149,177,177,177,1,1,1,148,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,151,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,165,1,1,145,192,146,193,177,177,177,147,1,1,1,159,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,146,1,149,192,192,161,197,177,177,162,1,1,1,1,160,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,166,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,146,145,177,177,177,177,201,177,177,158,1,1,1,1,164,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,165,177,177,177,177,177,201,177,147,1,1,1,1,145,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,205,147,1,1,1,1,156,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,177,195,1,1,1,1,1,168,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,21,21,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,1,177,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,147,1,1,1,1,1,160,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,21,21,1,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,156,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,162,1,1,1,1,1,1,152,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,146,1,251,248,249,250,1,164,177,158,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,177,177,146,260,254,253,261,1,160,177,147,1,8,157,153,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,177,177,177,177,155,177,154,263,253,266,242,1,148,162,153,153,149,165,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,21,21,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +177,177,177,177,177,159,159,159,177,154,160,147,1,1,1,1,1,1,148,161,165,165,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,21,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +176,177,177,177,158,1,1,160,151,1,159,1,1,1,1,1,1,1,164,177,177,177,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,248,260,254,253,1,1,1,21,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +176,176,177,177,167,1,1,1,159,1,1,1,1,1,1,1,1,1,156,177,177,167,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,266,263,1,266,1,1,1,1,21,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +64,176,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,164,177,151,152,167,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,176,176,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,177,151,1,159,152,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +1,176,159,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,164,166,1,1,1,152,166,1,157,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,176,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,154,1,1,1,168,154,145,146,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,166,1,1,1,156,166,149,177,146,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,1,1,1,1,1,241,242,243,240,1,1,1,1,1,1,1,1,1,168,154,1,1,1,168,165,177,177,154,1,248,260,254,253,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +1,1,1,1,1,1,245,266,247,244,251,248,249,250,1,1,1,1,160,162,153,1,1,145,177,177,177,151,1,1,266,263,1,266,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,177,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +0,1,1,1,1,1,249,267,1,248,260,254,253,261,1,1,1,1,1,168,161,146,1,149,177,177,177,162,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +1,1,1,1,1,1,237,238,1,266,263,1,266,242,1,1,1,1,156,177,177,146,145,177,177,177,177,146,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,1,1,1,1,1,241,255,1,1,1,1,1,1,1,1,1,1,1,168,163,177,165,177,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,4,4,32,28,24,4,4,4,4,4,4,1,4,4,4,4,4, +76,1,1,1,1,1,245,255,1,1,1,1,1,1,1,1,1,1,160,151,155,177,177,177,163,163,177,177,194,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,146,4,4,4,23,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,0,1,1,1,1,249,250,1,1,1,1,1,1,1,1,1,1,1,159,1,156,177,177,155,155,148,177,198,146,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,146,4,23,24,32,4,4,4,4,4,4,4,4,4,4,4,4, +76,1,1,1,1,1,237,238,255,1,1,1,1,1,1,1,1,1,1,1,1,152,163,150,1,1,152,200,177,150,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,150,4,4,4,32,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,1,1,1,1,241,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,155,152,150,1,1,196,177,177,150,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,194,23,32,28,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,1,1,1,1,245,246,1,256,242,243,240,241,242,243,240,241,1,243,240,241,242,159,240,241,242,148,177,177,150,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,200,194,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,1,1,1,1,246,247,244,245,246,247,244,261,1,247,244,245,246,247,244,245,246,247,152,177,177,150,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,202,200,194,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,250,251,248,249,250,251,248,249,250,251,248,1,1,1,248,249,250,251,248,249,250,251,148,177,177,150,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,63,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,202,202,200,146,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,76,1,1,238,239,236,237,238,239,236,237,238,239,236,1,1,1,1,1,1,1,255,1,1,239,1,148,177,177,150,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,200,202,202,178,158,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,76,1,1,242,243,240,241,242,243,240,241,242,243,240,1,1,1,1,1,1,243,255,1,1,243,1,148,177,177,150,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,196,200,202,178,147,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,76,76,1,246,247,244,245,266,247,244,245,246,247,244,1,1,1,1,1,1,1,250,1,1,1,1,1,148,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,196,200,177,162,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,76,1,1,250,251,248,249,267,1,248,267,250,251,248,1,1,1,1,1,1,1,238,255,1,1,1,1,148,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,196,177,177,146,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,76,1,1,238,239,236,237,238,1,266,237,238,239,236,237,262,239,236,1,1,1,242,1,1,1,1,1,1,152,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,146,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,242,243,240,241,255,1,1,241,242,243,240,241,242,1,1,1,1,243,246,1,256,1,1,1,1,152,177,177,154,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,146,4,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,267,247,244,245,255,1,1,245,246,247,244,263,1,247,244,1,1,1,244,245,246,1,1,1,1,1,168,177,166,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,150,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,1,1,1,1,250,251,248,249,250,1,1,249,250,251,248,1,1,1,1,1,1,248,260,254,253,251,1,1,1,156,177,177,154,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,146,4,4,4,4,4,4,4,4,4,4,4,4, +76,76,0,1,1,1,238,239,236,237,238,255,1,1,255,239,236,237,238,239,236,1,1,266,263,1,266,1,1,1,1,1,152,177,166,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,146,4,4,4,4,4,4,4,4,4,4,4, +76,76,1,1,1,1,242,243,240,241,242,1,1,253,242,243,240,241,242,243,1,1,1,1,1,1,1,243,1,1,1,1,168,177,150,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,177,146,4,4,4,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,246,247,244,245,246,1,256,1,246,247,257,245,262,247,244,245,246,247,244,245,1,247,1,1,1,1,156,177,177,150,246,1,256,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,177,177,177,177,146,4,157,4,4,4,4,4,4,4,4, +76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,154,1,4,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,248,260,254,253,1,1,1,1,152,177,177,177,177,150,149,146,4,4,4,4,4,4,4,4, +76,76,76,76,76,1,1,1,1,1,1,1,241,242,243,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,151,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,266,263,1,266,1,1,1,1,1,152,177,177,177,177,161,178,150,4,4,4,4,4,4,4, +76,76,76,76,76,1,1,1,1,1,1,1,245,266,247,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,1,1,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,146,4,4,153,153,153,153,149, +76,76,76,76,76,76,76,1,1,1,1,1,249,267,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,150,1,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,178,177,146,153,149,165,165,165,165, +76,76,76,76,76,76,76,1,1,1,1,1,237,238,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,154,1,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,165,165,177,177,177,177,177, +76,76,76,76,76,76,76,76,1,1,1,241,242,243,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,151,1,1,246,1,256,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,76,76,1,76,76,1,1,1,245,266,247,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,76,76,76,76,76,1,1,1,249,267,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,154,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,76,76,76,76,1,1,1,1,237,238,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,166,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,167,167,167,177,177,177,177,177,177,177,177, +76,76,76,76,76,1,1,1,1,1,1,241,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,150,1,1,1,1,1,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,159,159,155,152,177,177,177,177,177,177,177, +76,76,76,76,1,1,1,1,241,242,243,245,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,150,1,1,1,1,1,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,177, +76,76,76,76,1,241,242,243,245,266,247,249,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,150,1,1,1,1,1,242,1,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177, +76,76,1,1,1,245,266,247,249,267,1,237,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,150,1,1,1,1,1,246,1,256,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,63,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177, +76,76,1,241,242,243,267,1,237,238,1,241,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,63,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,167,167,167,167,167, +76,0,1,245,266,247,238,1,241,255,1,249,267,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,155,155,155,155,155,155, +76,76,1,249,267,1,255,1,245,255,1,237,238,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,237,238,1,255,1,249,250,1,241,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,63,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,241,255,1,250,1,237,238,255,245,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,167,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,245,255,1,238,255,241,242,1,249,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,152,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,63,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,249,250,1,241,242,243,255,1,237,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,151,1,152,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,63,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,0,237,238,255,245,266,247,255,1,241,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,166,1,1,152,177,177,158,1,1,1,1,1,1,1,1,1,1,1,1,63,76,76,76,76,1,63,76,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,241,242,1,249,267,1,242,243,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,168,150,1,1,152,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,76,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,1,1,1,237,238,1,266,247,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,156,177,154,1,1,152,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,76,64,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,76,1,1,241,255,1,267,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,168,166,1,1,1,168,177,146,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,63,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,76,1,76,245,255,1,238,1,1,1,248,260,254,253,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,156,177,154,1,1,160,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,63,63,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,249,250,1,255,1,1,1,266,263,1,266,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,168,166,1,1,1,152,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,63,0,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,237,238,255,255,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,156,177,154,1,1,1,152,177,177,146,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,64,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,241,242,1,250,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,168,166,1,1,1,1,152,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,1,1,237,238,255,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,156,177,154,1,1,1,1,152,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,1,1,241,242,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,168,151,1,1,1,1,1,152,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,1,1,1,1,1,1,156,166,1,1,1,1,1,1,168,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1, +76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,168,154,1,1,1,1,1,156,177,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,4,1,1,1,1,1,1,1, +76,76,1,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,156,166,1,1,1,1,1,1,152,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,4,1,1,1,1,1,1,1,1, +76,76,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,168,154,1,1,1,1,1,1,152,177,177,177,146,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,4,1,1,1,1,1,1, +76,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,156,166,1,1,1,1,1,1,1,152,177,177,177,146,1,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,168,154,1,1,1,1,1,1,1,152,177,177,177,150,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,156,166,1,1,1,1,1,1,1,1,152,177,177,177,146,153,1,1,1,1,1,1,250,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,168,154,1,1,1,1,1,1,1,1,152,177,177,177,165,150,1,1,1,1,1,238,255,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,160,166,1,1,1,1,1,1,1,1,1,152,177,177,177,177,150,1,1,1,1,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,1,1,168,154,1,1,1,1,1,1,1,1,1,152,177,177,177,177,146,1,1,1,1,246,1,256,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,145,166,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,4,145,177,154,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,150,1,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1, +76,0,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,1,255,1,1,1,1,1,255,1,1,1,168,177,177,177,177,146,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76, +76,1,1,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,1,1,255,1,1,1,1,1,255,1,1,156,177,177,177,177,177,150,1,1,1,1,1,1,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,166,1,1,250,1,1,1,1,1,250,1,1,1,168,177,177,177,177,177,150,1,1,1,1,1,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,154,1,1,238,255,1,1,1,1,238,255,1,156,177,177,177,177,177,177,150,1,1,1,1,1,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,166,1,1,242,1,1,1,1,1,242,1,1,1,148,167,177,177,177,177,177,150,1,1,1,1,1,246,1,256,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,154,1,1,246,1,256,1,1,1,246,1,256,1,159,152,177,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,194,1,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,163,177,177,177,206,150,1,1,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,159,148,177,177,208,177,150,1,1,1,1,1,1,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,177,208,177,177,150,157,153,1,1,1,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,206,177,177,177,165,165,150,1,1,1,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,196,177,177,177,177,177,177,150,1,1,1,246,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,177,151,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,148,177,177,177,177,177,177,150,1,1,1,1,1,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,151,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,1,1,148,177,177,177,177,177,177,150,1,1,1,1,250,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,166,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,148,167,167,177,177,177,177,150,1,1,1,1,238,255,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,154,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,159,159,152,177,177,177,177,150,1,1,1,242,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,2,152,177,177,177,177,150,1,1,1,246,1,256,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,166,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,152,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,154,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76, +80,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,168,151,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,2,152,177,177,177,162,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,145,151,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,255,1,1,1,152,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,153,145,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,255,1,1,1,1,152,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,161,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,250,1,1,1,1,152,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,1,1,1,1,238,255,1,1,1,1,152,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,242,1,1,1,1,1,152,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,248,260,254,253,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,166,1,1,1,1,1,1,255,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,246,1,256,1,1,1,1,152,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,266,263,1,266,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,158,1,1,1,1,1,1,255,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,152,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,147,1,1,1,1,1,1,250,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,0,1,1,1,1,1,1,1,1,1,1,152,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,147,1,1,1,1,1,1,1,238,255,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,152,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,153,1,1,1,145,162,1,1,1,1,1,1,1,242,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,0,1,1,1,1,1,1,1,1,1,1,1,168,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,146,1,1,145,177,154,1,1,1,1,1,1,1,246,1,256,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,156,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,150,2,149,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,148,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,146,145,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,148,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +64,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,177,177,165,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,148,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,64, +76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,168,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,153,149,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,161,177,177,177,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,148,177,177,177,177,177,177,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,164,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,152,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149, +76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,156,167,177,177,158,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177, +76,1,1,1,1,1,1,1,17,1,1,1,1,1,1,1,1,1,1,160,177,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,64,1,1,1,1,1,1,1,1,1,1,1,1,1,155,152,177,162,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,160,177, +76,1,1,1,1,153,153,153,1,1,1,1,1,1,1,1,1,1,1,148,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,2,152,177,158,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177, +76,11,1,1,1,156,165,165,154,1,1,1,1,1,1,1,1,1,1,157,168,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,255,1,1,1,1,1,1,1,76,76,76,1,1,1,2,168,162,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177, +76,11,1,1,1,168,177,166,1,1,1,1,1,1,1,1,1,1,156,165,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,1,1,1,1,1,1,76,76,76,76,1,1,1,156,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177, +76,11,1,1,1,156,177,177,154,1,1,1,1,1,1,1,1,1,1,168,177,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,250,1,1,1,1,1,1,1,76,76,76,76,1,1,2,168,177,158,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,177, +76,11,1,17,1,168,177,166,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,238,255,1,1,1,1,1,76,76,76,76,76,1,1,156,177,162,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,177, +76,1,11,1,1,156,177,177,154,1,1,1,1,1,1,1,1,1,1,168,177,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,242,1,1,1,1,1,1,1,76,76,76,76,1,1,2,168,177,150,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177, +1,11,4,1,1,167,167,151,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,246,1,256,255,1,1,1,76,76,76,76,76,1,1,156,177,177,158,1,1,1,1,1,1,153,1,1,1,1,1,1,157,157,157,1,1,1,1,1,1,1,1,1,168,177,177,177, +0,11,11,1,1,1,159,155,1,1,1,1,1,1,1,1,1,1,1,168,177,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,255,1,1,1,76,76,76,76,76,1,1,2,148,177,162,157,157,157,157,157,153,149,150,153,1,1,1,1,149,165,165,150,1,1,1,1,1,1,1,1,193,177,177,177, +0,11,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,250,1,1,1,76,76,76,76,76,1,1,1,148,177,165,165,165,165,165,165,165,177,165,146,1,1,1,145,177,177,177,150,1,1,1,1,1,1,1,145,197,177,177,177, +0,11,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,177,177,177,177,177,177,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,238,255,1,1,76,76,76,76,76,1,1,1,1,148,177,181,181,181,181,181,181,181,177,177,150,1,1,149,177,177,177,177,194,1,1,1,1,1,1,149,177,207,177,177, +0,11,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,177,177,177,177,177,177,177,177,177,177,154,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,242,1,1,1,76,76,76,76,76,1,1,1,1,148,181,181,181,181,181,181,181,177,177,177,194,157,145,177,177,177,177,198,150,1,1,153,153,153,145,177,177,203,177,177, +76,11,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,152,177,177,177,177,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,246,1,256,1,76,76,76,76,76,1,1,1,1,1,164,181,181,181,181,181,181,177,177,177,198,161,165,177,177,177,177,202,177,150,157,193,165,165,165,177,177,177,203,177, +76,11,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,152,177,177,198,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,149,181,181,181,181,181,181,181,177,177,204,177,177,177,177,177,177,202,177,177,165,165,197,177,177,177,177,177,177,205,177, +76,0,11,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,1,168,177,202,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,145,181,181,181,181,181,181,181,177,177,204,177,177,177,177,177,177,202,177,177,177,177,177,201,177,177,177,177,177,177,177, +0,0,11,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,156,177,202,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,149,181,181,181,181,181,181,181,181,177,204,177,177,177,177,177,177,202,177,177,177,177,177,177,201,177,177,177,177,177,177,177, +0,0,1,1,1,1,1,1,1,1,1,76,76,76,76,0,1,1,1,1,152,198,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,156,181,181,181,181,181,181,181,181,181,204,177,177,177,177,177,177,202,177,177,177,177,177,177,177,201,177,177,177,177,177,177, +0,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,196,177,177,177,177,177,151,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,168,181,181,181,177,181,181,181,181,206,177,177,177,177,177,177,200,177,177,177,177,177,177,177,177,201,177,177,177,177,177,177, +0,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,1,1,1,1,1,152,167,177,177,177,166,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,1,1,156,181,181,181,177,177,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,201,177,177,177,177,177, +0,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,1,1,1,1,1,155,152,167,167,167,158,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,201,177,177,177,177,177, +0,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,1,1,1,1,1,1,155,155,155,155,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,156,181,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,199,177,177,177,177, +0,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,168,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +0,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,181,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,145,177,181,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,149,177,177,181,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,0,0,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,1,1,1,1,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,149,177,177,181,177,181,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,0,0,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,1,1,1,76,76,76,76,76,76,1,76,76,1,1,1,1,1,1,1,1,1,76,76,76,76,1,149,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,0,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,1,1,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,76,1,1,76,76,76,76,76,156,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,1,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,76,76,1,76,76,76,76,76,1,168,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177, +76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,156,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177 + + + + +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,45,64,64,49,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,63,64,63,64,63,64,64,64,64,64,45,64,64,64,64,64,64,64,45,64,64,64,64,64,64,64,64,64,64,64,64,64,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,64,64,64,37,34,45,41,45,45,64,63,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,63,63,63,63,63,63,41,45,45,64,33,38,64,64,64,64,64,64,33,38,64,64,64,64,64,64,64,64,64,64,64,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,174,64,38,64,64,37,64,53,53,49,49,34,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,63,63,63,63,63,37,53,53,38,37,64,38,64,64,64,64,64,33,64,38,64,64,64,64,64,64,64,64,64,64,64,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,173,64,64,38,64,44,64,64,111,64,64,64,38,63,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,63,63,63,64,64,33,64,137,64,53,64,64,38,64,64,64,64,37,64,64,38,41,41,41,64,64,64,64,64,64,63,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,111,109,108,64,64,172,64,64,64,46,64,36,64,64,64,64,64,64,42,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,45,63,63,63,64,37,64,64,64,64,64,127,64,38,64,64,64,37,64,64,209,53,49,53,46,64,64,64,64,64,63,63,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,116,111,109,64,64,64,64,64,64,39,64,64,36,64,64,64,138,64,50,63,64,64,41,64,64,64,64,64,64,64,64,64,64,64,33,38,63,63,64,44,64,125,109,64,64,64,64,137,38,64,64,33,137,64,64,64,129,64,35,64,64,64,64,63,63,63,63,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,113,64,64,64,64,64,64,39,64,64,63,36,64,59,64,111,64,34,45,64,37,38,64,64,64,64,64,64,64,64,64,64,33,64,34,63,63,64,56,64,64,64,127,64,64,64,64,38,41,37,64,64,64,64,86,64,35,64,64,64,64,64,63,63,63,63,64,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,64,64,64,54,64,64,64,63,52,64,60,64,64,58,53,34,37,64,34,64,64,64,64,64,64,64,64,64,33,125,64,38,63,64,33,64,64,109,104,64,64,64,64,64,53,53,64,111,88,64,64,64,50,64,64,64,64,64,63,63,63,63,64,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,109,108,64,64,64,64,64,38,64,64,63,37,64,64,64,64,57,64,64,53,64,64,42,64,64,64,64,64,64,64,64,33,103,64,64,34,63,48,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,34,64,64,64,64,63,0,64,63,64,64,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,134,61,109,64,64,64,64,64,64,142,38,41,45,33,64,111,64,64,64,64,64,106,64,134,54,63,64,64,64,64,64,64,64,33,125,64,125,64,34,41,52,127,64,64,64,64,64,227,64,64,64,64,64,64,64,64,64,64,64,38,64,64,64,64,0,0,63,64,64,0,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,53,49,44,64,64,64,64,87,64,64,106,64,111,64,46,64,64,64,64,64,64,64,37,64,64,64,109,64,49,49,64,64,64,64,125,64,64,64,64,144,64,64,64,64,108,64,64,64,209,34,64,64,64,63,0,0,64,64,64,0,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,115,111,64,64,64,64,64,64,0,116,64,38,36,138,64,64,64,64,64,111,64,104,64,35,64,64,64,64,64,64,64,44,125,64,125,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,88,64,64,64,34,64,64,64,0,63,64,64,64,0,0,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,129,64,64,64,64,64,64,64,64,64,64,0,0,0,0,109,64,42,52,64,64,64,64,64,64,64,104,64,54,64,64,64,64,64,64,64,64,56,64,64,64,109,64,64,64,109,64,125,64,64,64,64,64,64,64,64,215,64,64,108,64,64,64,64,209,38,64,64,64,0,64,64,64,64,0,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,64,39,37,111,64,58,111,64,104,103,104,64,64,42,64,64,64,64,64,64,64,37,64,125,64,64,64,0,64,109,64,64,64,64,227,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,45,45,45,56,64,64,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,0,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,39,37,64,104,57,64,111,104,64,64,104,64,54,64,64,64,64,64,64,64,44,64,103,64,64,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,86,53,49,49,34,64,64,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,129,345,346,347,64,64,64,64,64,64,64,64,64,113,0,0,0,0,64,44,64,64,64,64,111,111,64,64,104,64,64,42,64,64,64,64,64,64,64,56,64,64,64,0,0,64,64,64,64,64,64,64,64,64,64,64,143,64,64,61,64,64,64,64,64,111,64,86,64,64,64,64,38,64,64,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,116,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,42,52,64,64,64,64,64,111,64,64,111,54,43,45,64,64,64,64,64,64,33,137,64,64,0,64,64,125,64,137,64,64,64,144,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,129,64,38,64,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,346,64,64,64,64,64,64,64,64,109,0,0,0,0,54,44,64,64,106,64,64,103,106,64,104,64,46,37,38,64,64,64,64,64,33,64,64,64,0,0,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,144,64,64,64,64,111,64,64,64,64,64,108,64,34,64,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,345,347,64,64,64,64,64,64,109,0,0,0,0,114,34,36,64,104,64,103,64,64,64,103,104,50,33,64,38,41,45,45,0,33,64,92,64,109,0,64,125,64,125,64,64,227,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,209,64,64,64,38,64,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,345,108,346,64,64,64,64,64,0,0,0,0,0,0,113,34,43,56,104,64,64,64,111,103,64,64,53,64,64,53,49,53,46,48,64,64,92,64,64,64,64,64,64,64,64,64,64,64,64,64,64,218,64,64,64,64,64,64,215,64,64,111,87,64,64,64,64,64,138,64,38,63,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,108,113,64,64,64,64,64,0,0,0,0,0,0,64,34,37,104,104,111,64,111,64,64,106,64,111,103,64,64,64,54,64,40,64,64,0,64,64,125,64,125,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,113,64,0,0,83,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,64,64,53,64,64,104,64,103,64,64,64,64,64,64,64,64,64,64,42,64,40,64,0,0,64,103,64,103,64,64,64,64,64,64,64,64,215,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,39,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,129,0,221,64,64,64,132,64,64,64,64,64,64,64,0,0,0,0,109,109,64,64,64,64,64,106,64,64,104,104,111,64,64,64,64,64,114,54,64,64,40,64,64,64,64,64,125,64,64,64,144,64,64,64,64,64,64,64,64,64,64,143,64,64,64,64,64,64,64,64,64,64,64,111,64,39,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,108,0,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,109,64,64,64,64,103,64,64,64,104,104,64,111,64,64,64,138,64,64,46,64,64,56,64,64,92,64,64,64,64,227,64,64,64,64,64,64,64,64,144,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,129,39,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,64,64,109,64,64,64,64,111,64,104,104,103,142,111,64,64,106,64,54,64,64,37,64,64,64,92,64,64,64,64,64,64,64,64,64,64,64,83,64,64,64,64,64,64,64,64,144,64,64,64,64,114,64,64,111,50,64,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,0,64,64,87,64,64,64,64,64,64,64,64,0,0,0,0,116,0,0,140,109,64,64,111,104,64,104,111,104,64,64,104,64,64,64,64,38,64,44,64,64,64,64,92,64,64,64,64,64,64,64,64,143,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,38,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,140,0,0,0,0,0,0,0,109,103,111,104,64,111,64,111,64,64,104,121,64,64,64,64,38,64,40,64,64,64,64,92,64,64,85,64,64,64,64,64,64,64,64,106,64,64,218,64,64,64,64,64,64,215,64,64,64,111,64,64,64,38,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +64,64,64,64,0,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,64,103,64,64,104,111,64,111,64,64,64,64,64,64,64,64,64,42,64,40,64,106,64,64,92,227,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,121,64,64,42,64,64,64,64,64,64,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,4, +64,64,64,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,0,0,0,0,111,64,64,64,64,104,64,111,103,104,64,64,104,64,64,64,39,64,64,56,64,64,64,64,64,64,64,64,64,64,218,64,64,64,64,64,64,215,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,64,64,64,64,64,64,33,53,49,53,49,49,53,49,53,49,53,49,53,49,53,38,4, +64,64,64,345,108,121,64,0,64,64,108,64,64,64,64,64,64,64,111,64,0,0,0,0,64,64,64,64,64,64,106,111,103,64,64,114,104,64,104,138,54,64,64,44,64,116,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,143,64,64,64,64,64,64,64,64,64,64,34,64,64,64,64,64,33,64,0,4,4,4,4,4,4,4,4,4,4,4,4,4,38, +64,64,64,108,64,0,64,345,347,64,64,64,64,64,64,64,64,111,64,64,0,0,0,0,106,64,104,64,64,64,103,111,64,64,64,64,104,64,104,64,42,64,64,56,64,64,64,64,64,64,64,64,64,215,64,64,64,64,64,64,64,64,85,144,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,64,64,64,64,33,100,64,0,64,116,64,64,64,64,64,64,64,64,64,64,64,46, +64,64,64,64,64,64,64,345,64,346,64,64,64,64,64,64,64,64,64,64,160,0,0,0,64,64,104,64,64,104,64,111,64,104,64,64,64,64,111,64,54,64,64,44,64,64,64,144,64,64,64,64,64,64,64,64,64,64,64,143,64,64,85,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,34,45,45,45,33,64,64,64,0,111,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,113,64,64,64,64,64,132,64,64,64,64,64,64,64,64,64,64,0,0,0,0,64,111,64,104,64,64,64,64,111,104,64,64,64,64,111,64,42,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,53,53,53,53,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42, +64,64,64,64,64,64,64,64,113,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,64,64,64,104,64,106,64,104,64,104,64,64,64,64,64,116,54,64,64,44,64,64,64,64,64,64,64,64,64,64,64,144,64,64,64,64,64,64,64,64,64,64,218,64,64,64,230,64,64,64,64,111,64,64,64,64,64,64,64,64,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,64,1,64,108,64,64,64,64,64,64,129,115,64,64,0,0,141,0,0,0,111,0,103,64,64,64,64,64,64,64,64,64,64,103,64,64,64,42,64,64,56,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,138,64,64,64,64,64,64,64,64,64,64,64,64,138,64,64,64,64,64,64,64,64,64,64,64,64,64,46, +64,64,64,64,345,347,64,64,64,64,64,64,64,64,64,109,64,0,0,0,0,0,0,0,0,64,64,142,64,64,64,64,64,64,64,64,64,64,64,64,54,64,64,44,64,64,64,64,64,64,64,64,64,64,64,106,64,64,218,64,64,64,64,64,64,215,64,64,64,64,64,64,64,64,64,64,108,114,64,64,64,64,64,64,64,111,64,108,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,108,345,64,346,64,64,64,64,64,64,64,64,109,64,0,0,0,0,0,0,0,0,104,64,64,64,106,64,64,103,106,64,64,64,64,64,64,42,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,114,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42, +64,64,64,64,64,64,64,64,64,64,64,64,64,109,118,114,64,0,0,0,0,0,0,0,0,64,104,64,64,64,103,64,64,106,64,142,64,116,64,64,39,64,64,44,64,64,64,64,64,64,218,64,64,143,64,64,64,215,64,64,64,64,64,64,64,64,64,64,230,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,64,132,64,64,64,64,64,64,64,64,115,109,64,64,0,111,0,0,0,134,90,0,64,64,103,104,64,64,64,64,64,64,64,64,64,64,39,64,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,103,64,0,0,0,0,0,0,89,0,209,64,64,64,64,64,64,64,64,104,64,64,64,64,54,64,64,64,44,64,64,212,64,64,64,64,144,64,64,64,64,64,64,64,64,64,64,64,143,64,64,64,64,64,64,64,64,108,64,64,121,64,64,64,98,64,64,100,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,89,0,0,64,92,64,64,104,111,104,64,64,64,64,111,64,64,42,64,64,64,40,64,64,64,64,64,115,64,64,64,64,64,64,64,82,144,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,46, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,116,0,64,82,92,64,64,64,104,64,111,64,64,111,64,138,54,64,64,64,64,40,64,64,85,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,64,111,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,90,0,0,0,64,64,112,111,64,64,64,111,64,64,64,103,64,64,38,64,64,64,64,56,64,88,64,64,64,64,64,64,64,64,64,64,64,64,64,64,218,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42, +64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,0,0,0,0,89,0,111,0,64,64,64,111,64,64,64,64,64,114,64,64,103,64,64,38,64,64,64,44,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,230,64,64,64,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,212,0,111,0,0,112,64,64,64,64,106,64,64,121,64,134,64,64,111,64,42,64,64,64,56,64,64,64,64,106,64,64,64,218,64,64,64,64,64,64,215,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,64,42, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,209,64,0,0,0,0,0,0,0,112,64,64,64,64,92,64,64,142,64,64,64,64,64,64,64,35,64,64,64,37,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,224,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,0,0,0,0,86,0,0,0,64,64,115,88,92,64,64,64,64,106,64,64,64,64,54,64,64,64,37,64,64,64,64,64,64,109,64,64,64,144,64,64,143,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,138,64,64,100,100,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,46, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,86,0,113,0,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,46,64,64,44,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,144,64,64,98,64,64,64,64,64,64,64,64,90,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,0,122,64,64,64,64,90,104,64,64,64,64,64,64,64,64,54,41,45,64,40,64,64,64,64,64,64,64,109,116,64,64,64,64,64,64,64,64,64,64,230,64,64,64,64,64,64,111,64,64,64,64,64,89,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,64,46, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,0,0,0,143,0,0,0,0,64,64,64,64,89,64,104,64,64,64,64,64,64,64,103,53,53,46,64,40,116,64,64,64,64,64,138,64,64,64,122,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,0,0,0,0,0,0,0,0,64,212,64,89,64,64,111,64,111,64,64,64,64,64,64,64,39,64,45,56,64,64,64,64,64,64,64,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,89,64,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,233,64,0,0,64,64,64,64,42, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,0,0,0,0,0,0,0,0,64,64,64,64,64,64,111,64,64,111,64,64,64,138,64,64,39,64,48,53,64,64,64,212,64,64,64,109,64,64,64,64,218,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,90,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,64,64,64,64,54, +64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,0,0,0,0,0,0,0,0,64,64,64,64,64,114,111,64,64,64,64,129,64,64,64,39,64,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,230,64,64,64,64,64,64,64,64,64,64,64,64,93,105,64,64,64,105,64,64,64,64,138,64,64,64,64,64,64,64,64,0,64,0,64,64,64,64,42, +35,36,64,64,64,64,64,64,64,64,64,113,64,64,64,64,64,0,0,0,0,0,0,0,0,64,64,64,64,64,64,111,129,64,64,64,64,64,111,64,54,64,64,64,56,64,64,64,64,122,64,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,0,64,64,64,64,54, +64,36,64,64,64,64,109,132,64,129,64,64,64,64,64,64,64,108,0,0,0,0,0,0,0,64,64,64,112,64,64,111,64,64,64,103,106,64,111,64,42,64,64,44,64,121,64,64,86,104,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,224,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,0,64,64,64,46, +64,64,36,64,64,221,64,70,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,112,64,64,111,64,104,64,64,64,111,64,64,39,64,64,64,56,64,64,64,64,64,104,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,224,64,64,111,64,108,64,64,64,64,64,64,108,64,111,64,64,64,64,64,64,0,64,64,0,64,64,64,54, +64,64,52,108,64,64,70,64,0,209,64,108,64,113,64,224,64,64,64,64,113,64,109,64,64,64,64,64,64,143,64,111,64,104,142,64,64,104,116,39,64,64,64,48,64,64,64,64,64,64,64,64,64,109,64,64,64,64,144,64,144,64,64,106,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,115,64,64,64,64,64,64,64,0,64,64,0,64,64,64,46, +64,64,37,108,108,64,64,64,64,0,64,64,64,64,64,64,64,64,64,64,64,109,109,116,64,143,64,64,64,64,64,106,121,104,64,64,64,64,64,39,64,64,64,64,56,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,109,106,64,121,64,64,64,64,64,64,64,64,111,111,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,0,64,64,64,0,64,108,64,54, +41,37,95,108,89,64,64,64,64,64,64,64,64,64,64,64,108,92,64,64,109,134,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,50,64,64,64,64,48,64,106,109,109,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,64,0,64,116,64,64,46, +44,53,64,96,89,64,64,87,64,64,84,64,64,64,64,89,108,108,64,64,64,109,115,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,46,64,64,64,64,56,106,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,99,64,64,111,64,64,64,64,64,64,0,64,64,0,64,64,64,64,54, +52,64,64,89,64,64,83,64,64,64,63,64,64,64,89,108,108,121,64,64,64,64,109,64,64,64,64,64,141,64,64,64,64,111,64,64,64,64,50,64,64,64,64,48,64,106,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,143,64,138,64,64,64,64,64,64,119,64,64,64,64,64,64,64,0,64,0,64,64,64,64,64,46, +44,64,64,64,64,64,64,64,64,64,63,64,64,64,64,92,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,106,46,64,64,64,64,56,64,106,64,64,64,64,64,212,64,64,64,64,212,64,64,64,64,64,64,115,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,0,0,64,0,64,64,64,64,54, +36,64,64,64,64,64,64,64,64,63,63,64,64,64,64,92,93,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,129,64,64,50,64,64,64,64,48,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,106,64,64,98,64,64,111,64,114,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,0,64,116,64,64,64,64,64,46, +64,36,130,115,64,64,64,64,64,63,63,64,64,64,64,64,92,64,64,64,64,64,64,64,64,64,64,64,64,64,69,64,64,64,64,103,64,64,64,46,64,64,64,45,56,64,138,64,64,64,64,64,64,83,64,64,64,64,64,64,64,98,106,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,108,64,64,99,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,138,54, +64,52,64,64,64,64,64,64,64,346,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,50,64,64,64,48,53,64,64,106,64,64,64,111,64,64,64,64,64,84,82,64,64,64,64,64,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,98,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,46, +64,44,64,64,64,212,67,64,64,345,347,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,138,64,46,64,64,64,40,64,116,64,106,92,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,36,64,86,64,64,67,64,64,116,64,346,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,129,64,64,116,64,64,64,54,45,64,64,64,40,64,116,64,106,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,39,56,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,46, +64,64,40,64,64,64,73,108,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,124,64,64,64,64,64,64,64,64,64,64,64,64,53,46,64,64,45,52,64,64,64,64,92,64,64,64,64,64,64,64,116,64,64,64,64,64,39,44,64,64,64,64,64,64,64,64,64,64,98,64,64,111,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,108,54, +64,64,40,64,64,67,64,108,64,64,64,64,64,64,64,64,64,64,115,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,39,64,64,37,53,64,64,64,64,64,115,64,64,109,64,64,64,64,116,64,64,143,64,39,64,40,56,64,64,64,64,64,64,138,64,64,64,64,64,143,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,138,64,64,64,46, +64,64,64,40,64,64,88,64,64,109,64,93,64,209,134,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,104,111,64,64,39,64,64,37,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,39,64,64,48,64,64,64,64,64,64,64,138,64,64,105,64,64,111,64,64,64,99,64,64,64,64,64,119,64,64,64,64,64,111,115,64,64,64,54, +64,64,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,138,64,64,111,64,39,64,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,54,64,64,64,56,138,64,64,64,143,64,64,64,64,64,105,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,138,64,111,64,64,64,64,64,46, +64,64,64,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,50,45,64,64,56,64,64,64,64,109,109,64,64,64,64,64,121,64,64,64,64,121,64,109,42,64,64,48,64,64,116,64,64,64,64,64,64,64,105,64,115,111,64,64,64,64,64,64,64,64,111,116,64,64,64,64,111,64,64,64,64,64,54, +64,64,64,64,56,64,66,64,64,64,64,64,64,64,114,64,64,108,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,135,64,53,34,64,37,64,64,64,121,64,64,64,109,64,92,64,64,64,64,64,64,64,64,64,54,64,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,124,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,46, +64,64,64,64,44,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,37,64,64,64,64,64,64,64,106,64,64,92,64,64,64,64,64,64,64,64,64,42,64,64,37,64,64,108,64,64,64,108,64,131,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,54, +64,64,64,64,56,66,66,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,103,64,64,64,64,53,64,64,64,64,64,64,64,64,64,64,64,92,64,64,64,138,64,93,64,64,54,64,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,111,64,64,64,46, +64,64,64,64,37,64,66,66,109,108,64,64,64,64,116,346,64,64,64,64,64,64,140,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,143,64,64,64,111,96,64,64,64,64,94,64,64,54,46,64,64,56,64,64,64,64,64,64,64,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,115,111,64,64,64,54, +64,64,64,33,116,64,66,64,64,64,108,64,64,64,64,345,347,64,64,140,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,89,64,106,64,38,64,64,48,64,64,64,64,64,111,64,116,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,64,138,64,64,64,64,64,64,64,64,64,46, +64,64,64,37,64,64,64,64,64,64,64,64,64,64,64,345,64,346,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,121,64,64,103,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,115,64,38,64,64,36,64,64,64,64,64,111,64,64,64,64,105,64,64,64,64,64,116,64,64,99,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,33,64,64,64,212,64,66,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,140,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,115,64,42,64,64,36,64,64,108,64,64,64,64,64,105,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,138,64,46, +64,64,44,64,63,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,116,64,64,64,64,64,64,64,141,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,115,64,64,64,116,64,64,64,106,64,64,64,64,39,64,64,64,52,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,54, +64,64,36,129,64,108,64,64,66,64,66,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,39,64,64,64,37,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,64,64,64,64,64,111,64,64,64,64,64,46, +64,64,64,36,63,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,129,64,64,64,129,64,139,64,64,64,64,64,64,64,64,64,64,64,143,64,64,64,64,64,39,64,64,64,37,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54, +64,64,64,43,40,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,139,116,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,39,64,64,64,44,64,64,64,64,64,64,135,111,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,53, +64,64,64,64,64,40,64,64,64,0,64,64,64,64,109,64,115,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,54,64,64,64,64,56,64,64,64,64,64,64,111,64,64,64,64,64,64,115,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,63,52,64,64,0,0,64,64,64,141,64,64,64,64,64,64,64,64,64,64,64,143,64,64,64,114,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,46,64,64,64,37,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,44,35,52,64,0,64,64,64,64,64,64,140,64,64,64,64,64,64,64,64,121,346,64,64,64,64,64,64,64,64,64,106,103,64,64,64,64,104,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,131,54,64,64,64,37,64,121,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,43,44,64,64,0,108,64,64,64,64,64,64,121,64,64,64,64,64,132,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,42,64,64,44,64,64,64,64,138,64,64,64,111,64,64,64,64,64,64,64,64,64,64,115,64,64,64,64,99,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,40,64,64,64,64,64,64,108,64,346,64,64,136,64,64,133,64,64,64,64,64,64,64,140,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,131,64,64,64,64,64,108,64,64,64,64,64,64,54,64,64,64,40,64,64,64,64,64,64,64,115,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,40,64,64,64,64,64,64,108,64,64,64,64,64,335,64,332,64,347,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,106,64,64,64,64,108,138,64,64,108,64,64,64,64,64,64,38,64,64,64,40,64,64,64,64,64,64,64,111,64,105,116,64,64,64,64,64,98,64,108,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,40,55,64,64,64,64,64,64,64,64,64,140,64,346,64,64,344,64,64,64,129,64,64,64,64,64,64,64,64,111,64,64,111,111,64,106,64,64,64,64,64,64,64,64,64,108,64,106,64,64,64,64,64,38,64,64,64,56,64,64,64,64,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,100,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,63,47,40,64,64,64,64,64,64,64,64,64,64,64,64,64,339,64,64,64,64,344,0,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,46,64,64,37,64,64,64,64,64,108,108,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,100,64, +64,64,64,64,64,45,45,45,45,63,40,64,64,64,347,347,0,347,64,64,142,64,336,64,346,64,64,346,347,64,140,64,64,137,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,143,64,64,104,64,64,35,64,64,33,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,111,64,111,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,37,53,53,53,38,64,56,64,64,64,64,64,0,340,64,64,64,64,64,64,64,64,64,64,133,342,64,64,64,64,64,64,64,64,64,139,64,108,64,64,64,123,64,64,64,64,64,64,64,64,64,64,64,64,64,64,35,64,64,37,64,64,64,64,64,116,64,64,64,64,64,64,64,108,64,64,64,64,111,64,64,111,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,37,64,106,64,64,38,37,64,64,347,64,333,64,0,342,347,64,64,345,137,64,64,64,64,0,64,64,64,344,345,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,35,64,64,33,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,111,64,109,64,64,64,64,64,64,64,64,64,100,64,64,64, +64,64,64,33,64,126,64,109,136,53,64,64,64,64,64,64,64,64,347,0,64,140,64,64,0,64,64,0,64,64,64,64,64,64,66,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,35,64,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,98,64,64,109,64,64,64,64,64,64,64,64,64,64,64,0, +64,63,41,33,126,109,64,126,64,64,136,64,142,64,64,116,64,64,64,346,346,0,64,64,0,334,135,140,64,64,64,132,64,64,175,66,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,35,64,64,64,40,64,64,64,64,64,64,64,105,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,109,64,64,64,64,115,64,64,64,64,64,64,64, +64,48,53,64,106,64,64,64,64,109,64,64,64,64,64,64,64,64,64,142,64,0,64,64,0,64,64,64,64,64,64,64,64,64,66,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,36,64,50,64,64,64,64,52,64,131,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,116,64,64,105,64,64,64,109,64,105,64,64,64,64,64,64,64,64,64,0, +64,63,36,136,109,64,128,64,128,64,64,64,64,64,64,64,64,133,64,64,0,0,64,136,64,0,64,64,64,129,64,64,64,64,66,66,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,46,36,64,38,64,64,64,37,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,121,64,64,64,64,64,64,64,64,50, +64,63,36,64,126,64,64,64,104,64,64,64,64,114,64,345,64,64,64,64,0,64,64,64,65,64,133,64,335,64,64,64,64,64,66,175,64,64,64,64,64,64,64,104,64,64,64,143,64,64,64,64,111,64,64,35,64,36,64,38,64,64,37,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,105,64,98,64,64,64,64,64,64,64,64,64,64,42, +64,64,64,52,64,104,64,64,64,64,64,64,140,64,64,344,137,64,345,141,64,64,139,64,65,65,64,337,64,0,64,64,64,64,66,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,111,64,64,35,64,64,36,64,42,64,33,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,115,64,64,64,64,105,64,64,64,64,64,64,50, +64,64,44,64,64,64,106,109,64,64,64,64,64,64,64,64,333,64,64,64,0,64,65,64,65,65,64,64,64,64,64,343,346,64,64,64,64,64,64,64,64,108,64,64,64,106,111,64,64,64,64,64,64,39,43,64,64,64,52,35,64,37,64,64,64,64,64,64,104,64,64,64,64,64,108,64,64,64,108,64,98,64,64,64,133,64,64,64,64,64,64,64,105,64,64,64,64,64,115,64,42, +64,64,64,56,128,109,64,64,64,64,64,64,64,64,64,64,64,64,347,141,0,64,65,344,65,65,65,64,64,64,64,64,347,64,175,64,64,64,64,64,139,64,64,64,64,64,111,64,64,64,64,64,64,39,64,64,64,64,48,50,64,44,64,64,121,64,64,143,64,104,64,64,64,64,108,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,109,64,109,50, +64,64,44,64,64,126,64,64,64,64,64,64,64,64,137,64,64,345,347,64,64,64,65,345,65,64,65,0,131,144,116,142,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,111,64,54,64,64,64,63,64,52,42,64,40,64,64,64,64,64,64,64,104,64,64,64,64,64,108,64,64,64,64,109,64,64,109,64,64,64,64,64,98,105,64,64,64,64,64,64,64,64,109,42, +64,64,64,36,64,64,64,64,64,64,64,64,64,121,64,64,140,64,64,64,64,65,65,54,43,43,56,65,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,108,64,64,64,64,46,64,64,63,63,37,39,64,64,40,64,63,64,64,64,64,104,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,50, +64,64,64,36,64,63,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,65,65,42,65,44,64,65,347,340,64,64,64,64,64,64,98,64,64,64,64,64,64,64,64,111,64,108,64,64,64,64,54,64,64,64,63,33,39,64,64,64,52,63,63,63,63,63,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,98,64,64,64,109,42, +64,64,64,64,36,63,64,64,64,64,64,64,64,64,0,64,116,64,133,64,64,65,65,39,64,64,40,65,64,64,64,64,64,64,64,64,133,64,64,64,64,64,64,111,64,111,64,64,64,64,64,64,64,46,64,64,63,37,54,64,64,64,33,63,63,63,63,63,63,64,64,64,64,111,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,50, +64,64,64,64,47,47,40,64,64,64,64,64,64,64,0,64,64,64,64,64,143,65,39,64,65,64,40,65,141,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,139,64,64,64,64,64,139,64,54,64,64,64,37,64,42,64,64,33,63,63,1,63,63,63,64,64,64,64,64,64,111,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,139,64,109,42, +64,64,64,64,64,64,64,40,64,64,64,140,64,64,0,64,64,64,64,64,64,39,43,64,65,64,65,56,64,64,64,114,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,38,64,64,48,64,54,64,64,37,63,63,1,1,63,63,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,50, +64,64,64,64,64,64,64,56,64,64,64,64,64,64,0,64,64,64,132,64,39,65,65,64,65,65,44,121,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,64,64,52,64,38,64,48,64,63,63,35,1,63,63,64,64,64,64,64,64,64,64,105,64,64,64,39,43,43,43,43,40,64,39,43,40,64,64,64,64,64,109,64,64,64,64,42, +64,64,64,64,64,64,64,44,64,64,64,346,64,64,0,64,0,133,64,64,54,65,65,64,65,65,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,64,33,64,64,38,41,56,63,63,35,48,1,63,63,64,64,116,64,64,64,64,64,64,64,64,39,64,64,64,64,64,40,39,64,64,40,64,64,139,116,109,64,64,64,64,50, +64,64,64,64,64,64,41,56,64,64,64,64,347,347,0,335,0,332,64,347,42,65,64,64,65,65,41,56,64,64,64,137,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,131,64,111,64,64,64,111,38,37,64,64,64,53,53,64,63,35,64,36,1,63,64,64,64,64,64,64,64,116,64,64,64,39,64,64,64,64,64,64,43,64,64,64,43,40,64,64,64,109,64,64,64,64,42, +64,64,64,64,64,64,37,53,64,64,64,64,64,64,0,64,0,64,64,344,39,65,65,65,65,65,37,53,64,64,64,64,64,64,64,64,98,64,210,64,64,64,64,64,64,64,64,111,64,64,111,64,64,111,64,49,64,64,64,64,64,64,63,50,41,64,36,63,63,143,64,64,64,133,64,64,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,64,40,64,64,64,64,98,64,64,50, +64,64,64,64,64,44,64,140,64,64,64,347,64,64,0,64,64,0,339,39,0,65,65,65,65,44,64,64,64,64,344,345,64,64,64,64,64,64,64,64,64,64,64,64,64,111,111,111,111,64,64,64,64,111,64,64,64,64,64,64,64,63,63,49,42,64,36,63,64,64,64,64,64,64,105,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,64,64,40,64,64,64,64,64,64,64,42, +64,64,64,64,64,64,40,64,64,64,64,129,347,64,0,142,347,0,64,54,41,65,65,65,65,65,36,64,64,64,64,64,345,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,111,64,64,64,64,64,64,64,104,63,64,39,64,64,36,63,64,64,64,64,64,64,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,64,64,64,56,64,105,64,64,64,64,50, +64,64,64,64,64,64,52,346,64,64,136,64,340,133,0,64,64,346,64,53,38,65,65,65,65,65,36,64,64,64,64,64,347,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,63,63,39,64,64,64,56,64,64,64,64,64,64,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,64,64,64,44,64,64,64,64,64,64,64,42, +64,64,64,45,64,64,44,64,64,64,333,335,64,332,0,347,64,345,64,64,64,42,65,65,65,64,65,36,64,140,64,64,64,64,64,64,64,64,64,122,64,64,64,64,64,64,64,64,64,64,64,64,105,64,64,64,64,108,64,64,64,64,63,39,64,64,64,48,64,64,64,64,64,64,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,56,64,98,64,64,139,64,50, +64,64,33,38,45,41,56,64,64,64,64,64,346,64,0,344,64,64,137,0,35,65,65,65,64,64,41,56,116,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,108,64,131,64,63,54,64,64,64,64,56,64,64,64,64,64,64,64,64,54,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,33,64,64,98,64,64,64,64,42, +64,64,33,64,53,53,53,64,64,64,64,64,64,345,0,346,64,64,64,64,35,64,65,65,64,64,37,53,64,64,64,64,138,347,64,64,111,121,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,63,38,64,64,64,37,64,64,64,64,64,64,64,64,64,42,64,64,64,64,64,64,64,64,64,64,64,64,64,64,37,64,64,64,64,64,64,64,50, +64,33,64,64,64,64,64,129,347,64,64,142,64,336,142,346,345,64,64,54,64,65,65,65,64,33,65,345,64,64,64,64,64,64,64,64,111,121,105,98,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,63,38,63,64,37,63,64,64,64,64,64,64,64,64,54,64,64,64,64,64,64,64,64,64,64,64,64,64,64,33,64,64,64,64,64,64,64,64,42, +64,37,64,59,64,64,64,64,340,64,64,64,133,64,0,64,64,64,136,133,38,64,64,64,64,37,65,0,64,343,346,64,64,64,64,64,111,64,64,105,64,133,64,64,64,64,64,64,64,64,64,121,64,64,64,64,108,108,64,64,64,64,63,64,38,63,37,64,63,64,64,64,64,64,64,64,64,38,64,64,64,64,64,64,64,64,64,64,64,64,64,33,64,64,64,64,64,64,64,64,50, +44,64,64,60,64,64,333,64,64,342,64,64,64,345,64,64,347,65,64,64,34,64,64,335,33,64,64,64,64,64,347,64,345,64,64,64,111,64,64,111,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,63,64,38,37,64,63,64,64,64,64,64,64,109,64,64,38,64,64,64,64,64,64,45,64,64,64,41,64,37,64,64,64,64,64,64,64,64,64,42, +64,36,64,64,64,64,64,64,64,64,64,137,137,64,141,64,64,64,65,64,64,38,64,64,33,64,64,64,64,64,64,64,64,64,64,64,64,111,64,111,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,108,64,63,64,63,53,64,63,64,64,64,139,64,64,109,109,64,64,46,64,64,64,64,64,37,38,64,64,33,34,33,64,64,64,64,64,39,47,36,64,50, +64,36,122,64,87,64,64,64,64,64,64,346,0,64,64,342,334,65,64,64,64,34,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,111,111,111,64,105,64,64,64,64,64,64,64,64,64,64,143,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,45,45,41,41,41,37,64,38,64,37,64,53,64,98,109,64,64,39,64,64,36,64,64, +64,64,52,64,64,64,64,64,64,64,142,64,64,64,64,114,64,64,64,64,64,64,38,64,64,64,64,64,64,114,64,108,64,64,64,64,102,64,64,111,64,105,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,53,53,53,53,53,53,64,64,34,33,64,64,64,64,64,64,64,39,64,64,64,36,50, +64,37,64,64,64,64,64,64,133,116,64,64,345,114,114,0,64,64,64,64,64,64,38,41,56,64,142,64,114,64,64,108,64,64,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,117,64,64,64,64,64,64,64,64,64,64,49,64,64,64,64,64,64,64,39,64,64,64,64,36,42, +64,44,64,64,64,64,64,64,64,64,64,114,64,64,64,64,142,133,64,335,64,64,64,53,53,64,64,64,64,64,129,64,64,64,64,64,64,64,105,64,111,64,107,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,39,64,64,64,64,64,47, +64,40,64,64,64,64,64,137,64,64,114,64,64,64,64,64,64,347,64,64,64,64,64,347,340,64,64,64,64,64,106,64,64,64,64,64,64,64,105,64,111,64,107,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,109,109,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,104,64,54,64,64,64,64,64,64,64, +64,64,40,64,64,64,64,333,64,64,64,342,64,133,64,142,64,64,64,64,64,64,334,64,64,64,64,64,64,106,110,64,64,64,64,64,64,64,105,64,111,64,107,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,139,64,64,64,64,64,64,64,64,64,109,109,64,64,106,116,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42,64,64,64,64,64,64, +64,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,110,64,64,64,64,64,64,64,64,105,64,111,64,121,111,64,102,64,64,64,64,64,64,64,64,64,64,111,111,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,107,64,64,64,64,107,64,64,64,140,64,64,64,109,109,107,64,64,64,50,41,64,64,64,64,64,64, +64,41,41,56,64,64,64,64,345,347,64,64,64,64,64,64,64,337,64,131,144,64,142,64,64,64,64,110,64,110,64,64,64,64,64,64,64,105,111,64,64,64,64,111,111,64,102,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,109,117,64,64,64,107,64,106,64,64,64,64,64,109,64,64,106,64,64,64,107,64,64,116,64,53,38,64,64,64,64,64, +37,53,53,64,64,64,64,64,64,64,64,64,142,64,64,64,64,64,64,64,64,64,64,64,64,64,64,110,64,64,64,64,64,64,64,111,64,64,111,64,64,64,111,64,111,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,131,64,64,116,64,109,64,64,64,64,64,106,64,64,64,64,64,109,64,64,64,64,106,106,107,64,64,64,64,64,64,34,64,64,64,64,64, +44,64,64,64,64,64,64,64,64,64,64,134,64,347,121,64,116,64,64,347,340,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,111,64,64,102,98,64,111,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,109,106,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,34,64,64,64,64, +36,64,64,64,64,64,64,64,64,133,64,64,64,64,64,64,64,64,334,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,98,64,64,102,98,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,106,64,64,64,109,64,64,64,64,64,64,104,64,106,116,64,64,114,64,64,64,64,64,64,64,64,38,64,64,64,64, +64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,111,64,64,102,98,64,64,64,121,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,109,64,64,64,64,64,64,109,64,106,109,64,64,64,64,64,64,107,106,64,64,64,64,38,64,64,64, +41,56,64,64,64,64,64,64,110,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,142,64,64,64,108,64,64,64,64,64,64,111,64,111,64,102,64,98,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,114,64,64,106,64,64,64,64,109,64,114,64,64,64,64,64,106,109,64,64,64,64,64,64,107,106,64,64,64,64,34,64,64,64, +44,53,64,64,141,142,64,144,64,110,64,64,64,64,64,64,64,64,64,64,64,64,116,129,64,64,64,64,64,64,64,64,64,64,64,121,111,64,64,121,102,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,64,107,64,64,109,64,64,64,64,109,64,64,64,64,64,64,64,106,64,109,64,64,64,109,109,64,64,106,64,64,109,64,38,64,64, +36,64,64,64,64,64,64,64,110,64,64,64,64,64,64,64,64,64,64,64,108,64,115,64,64,64,64,64,64,64,64,64,64,64,64,64,111,107,64,64,102,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,104,64,109,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,106,64,64,109,64,38,64,64, +64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,102,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,109,64,64,64,64,109,64,107,64,64,64,64,64,64,64,106,64,64,64,64,107,64,106,64,107,64,64,64,38,64, +64,36,64,64,64,64,64,64,64,64,64,64,134,64,64,64,64,129,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,111,64,64,64,64,64,39,36,64,64,64,121,102,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,109,64,107,64,109,64,64,64,64,106,90,91,64,64,64,64,64,64,116,64,64,64,64,38,64, +64,64,36,55,64,64,64,64,64,64,64,64,64,108,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,107,64,111,64,64,64,64,64,64,39,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,107,64,109,109,64,107,64,109,64,64,109,64,107,93,64,92,64,140,64,109,64,64,64,64,64,64,64,42, +64,64,47,36,64,64,64,64,64,64,64,64,64,106,64,142,64,64,64,64,64,64,64,64,64,64,64,64,110,64,64,64,64,64,64,107,111,64,64,64,64,64,64,39,64,64,36,64,64,64,136,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,107,64,109,109,109,64,64,64,64,64,64,64,64,109,64,104,64,64,64,64,64,39,64, +64,64,45,64,52,64,64,64,64,64,64,64,64,64,64,64,64,64,64,114,64,64,64,64,64,114,64,138,110,64,64,64,64,64,105,107,98,135,64,64,64,121,64,39,64,64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,123,64,64,64,64,64,64,109,107,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,39,64, +63,37,38,44,64,64,64,64,64,64,64,64,64,110,64,64,64,64,64,64,64,64,64,64,64,64,64,110,64,64,64,64,64,105,64,98,111,102,111,111,64,64,54,64,64,64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,39,64,64, +64,33,64,38,52,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,134,64,64,64,64,64,107,105,64,64,64,64,111,111,64,64,64,42,64,64,64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,89,92,93,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,39,64,64, +37,63,64,53,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,134,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,50,64,64,64,64,64,40,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,107,64,116,89,64,92,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,109,54,41,64,63, +44,63,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,64,106,108,64,64,64,134,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,107,64,64,38,64,64,64,64,64,40,64,64,64,102,121,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,89,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,53,38,63, +36,64,64,64,64,64,64,134,64,64,138,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,107,111,64,64,38,64,64,64,64,64,40,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,109,109,64,64,64,104,109,117,64,64,93,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,38,63, +64,36,64,116,64,64,64,64,132,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,121,64,64,111,98,64,64,38,64,64,64,64,64,40,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,109,107,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,46, +64,36,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,114,64,64,64,64,64,64,64,64,64,64,64,64,64,64,121,64,111,64,111,64,105,64,98,64,64,64,38,64,64,64,64,64,40,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,39,63, +64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,142,64,64,64,64,138,64,64,106,64,64,64,64,64,64,64,64,64,64,111,64,105,64,64,64,64,64,64,42,64,64,64,64,64,40,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,221,64,64,64,64,39,64, +64,64,56,64,138,64,64,64,64,64,64,123,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,111,64,111,121,64,64,64,64,35,64,64,64,64,64,64,40,64,64,64,64,111,64,105,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,41,64, +64,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,110,64,64,64,64,64,64,64,64,64,64,111,64,105,64,64,111,105,64,64,64,64,35,64,64,64,64,64,64,64,40,64,64,64,64,111,105,64,64,64,64,64,64,64,64,117,64,64,114,64,64,64,64,64,64,64,64,64,64,64,64,109,64,221,64,64,64,64,64,64,64,64,64,64,64,64,64,53,42, +64,64,56,64,64,64,64,64,114,64,64,64,64,64,64,110,110,64,64,106,110,110,64,64,64,64,64,64,64,64,64,64,64,111,121,105,64,107,111,64,64,64,64,35,64,64,64,64,64,64,64,64,56,64,105,64,64,111,121,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,114,64,64,64,64,64,109,64,64,82,64,64,64,209,64,109,64,64,64,64,64,64,54,64, +64,64,37,64,64,64,64,64,64,64,64,64,64,64,64,107,64,110,64,106,64,64,64,64,110,106,64,64,64,64,64,64,64,64,105,64,64,64,64,64,64,64,64,35,64,64,64,64,64,64,64,64,48,64,105,64,64,98,64,105,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,42, +64,33,64,64,64,64,64,64,64,64,64,64,64,64,107,64,64,110,64,64,64,64,64,64,110,64,64,64,64,64,64,105,64,111,105,64,64,64,107,64,64,64,35,64,64,64,64,64,64,64,64,64,56,64,105,64,64,64,64,105,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,64,64,64,64,221,64,64,109,64,64,64,64,64,64,64,64,109,106,64,106,64,64,64,54,64, +64,37,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,105,105,105,107,64,111,111,64,102,64,64,50,64,64,64,64,64,64,64,64,64,48,64,105,111,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,106,64,64,114,64,64,109,64,64,64,64,64,64,109,64,64,106,64,64,64,84,64,109,106,64,107,64,64,64,42, +44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,102,64,64,105,107,64,64,111,64,102,64,64,34,64,64,64,64,64,64,64,64,64,56,64,105,102,111,111,64,107,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,109,64,64,83,64,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,107,64,209,54,64, +64,36,64,64,64,64,64,64,64,64,64,64,64,138,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,105,64,111,107,111,64,64,64,64,64,64,34,64,64,64,64,64,64,64,64,48,64,105,64,64,64,111,111,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,109,64,64,64,83,64,64,64,64,64,64,64,107,64,64,64,64,64,64,64,107,64,64,64,42, +64,36,64,64,64,64,138,64,64,64,142,64,64,64,64,64,64,64,113,64,64,64,64,64,64,64,64,64,64,64,64,64,107,111,64,64,64,64,64,64,64,64,64,34,64,64,64,64,64,64,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,109,64,107,64,64,64,64,64,64,64,106,64,64,107,64,64,64,64,64,64,64,64,64,64,54,64, +64,64,36,64,134,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,64,64,111,64,102,111,111,121,64,105,64,64,64,34,41,41,64,64,64,64,64,48,64,64,64,64,135,107,64,111,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,104,64,64,64,64,64,64,64,64,64,64,42, +64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,64,64,64,64,109,64,64,64,64,102,64,111,64,64,105,64,64,64,53,53,38,64,64,64,64,64,56,64,64,64,64,107,64,64,111,64,64,64,64,64,64,64,64,64,107,64,109,64,64,64,64,106,64,107,64,64,64,64,64,106,64,64,64,64,64,64,64,64,64,64,64,64,64,54,64, +64,64,64,56,64,103,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,64,64,64,64,109,64,64,98,111,102,111,111,64,64,64,64,64,64,64,64,64,38,64,64,64,64,37,64,98,64,111,64,107,121,111,64,64,64,64,64,64,64,64,64,64,107,109,64,64,64,64,64,106,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,122,42, +64,64,44,116,64,103,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,64,64,102,64,64,111,64,102,64,64,64,98,64,64,64,64,127,64,42,64,64,64,37,64,64,121,64,111,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,109,64,104,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,64, +64,64,64,56,64,103,64,64,64,64,64,64,64,64,113,64,64,64,64,64,64,64,99,64,99,64,64,64,64,64,64,102,64,64,111,64,102,64,64,64,98,64,105,64,64,64,64,39,64,64,64,37,64,64,64,64,105,111,64,64,111,105,121,64,64,64,64,64,64,64,64,64,64,109,64,64,64,104,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,42, +64,64,33,64,64,64,64,64,64,64,64,64,64,64,64,64,129,64,109,64,64,64,64,99,99,64,64,64,64,64,64,102,121,64,64,111,102,64,64,64,98,136,64,64,64,64,39,64,64,64,44,64,64,64,64,105,111,64,64,111,64,105,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,88,64,64,64,64,64,209,64,109,64,54,45, +64,64,37,64,64,64,117,64,64,64,64,64,64,64,64,64,64,64,109,64,64,99,64,64,64,64,64,64,64,64,64,109,102,64,64,111,111,64,64,64,98,64,64,64,64,64,39,64,64,64,64,40,64,64,64,64,64,64,64,111,105,64,64,64,64,64,64,64,64,64,64,64,64,64,117,64,64,64,109,64,64,64,64,64,64,64,64,209,64,64,64,221,64,64,64,64,64,109,64,64,53, +64,33,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,64,99,99,64,64,64,109,102,64,64,64,64,107,111,98,64,64,107,64,64,54,64,64,64,64,64,40,64,64,64,64,64,98,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,221,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64, +64,37,64,64,64,64,64,64,64,209,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,64,64,64,64,64,64,109,102,64,64,64,64,64,107,98,64,64,107,64,64,64,38,64,64,64,64,64,40,64,64,64,64,64,64,111,64,64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,104,64,64,64,64,64,64,64, +44,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,134,64,64,64,99,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,111,98,64,64,102,64,64,64,38,64,64,64,64,41,40,64,64,64,64,64,105,111,64,64,64,64,64,64,64,64,64,64,64,64,116,64,64,64,64,64,64,109,64,85,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,87,64,64,64, +64,40,64,64,64,64,64,64,64,64,64,134,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,99,99,64,64,109,64,64,64,64,64,64,64,111,64,64,64,102,121,64,64,38,64,64,64,37,38,40,64,64,64,64,64,111,64,64,64,64,64,55,64,64,64,64,64,64,64,107,64,64,64,64,64,109,64,64,85,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64, +64,56,64,64,64,64,64,64,64,64,64,64,64,64,109,116,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,109,64,107,64,111,121,64,64,111,64,64,64,121,64,64,63,38,64,64,37,64,38,56,64,64,111,64,111,64,64,64,64,39,43,56,64,64,64,64,64,64,64,64,64,106,64,64,64,109,64,64,64,64,109,64,64,64,104,64,64,64,64,64,109,64,64,64,64,64,64, +64,37,64,221,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,99,64,64,64,64,99,64,64,64,64,109,105,64,111,121,105,64,111,105,64,64,111,64,64,64,63,38,41,37,64,64,53,64,64,102,111,111,64,64,64,64,39,64,44,64,64,64,64,64,64,64,64,64,106,64,64,64,64,106,64,64,64,64,106,64,64,64,109,64,64,64,64,109,64,106,64,64,64,100, +44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,99,64,64,64,64,64,64,64,64,64,64,64,109,105,64,111,121,105,64,111,105,64,64,111,64,64,64,64,53,53,64,58,64,64,64,64,102,64,111,64,64,39,43,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,64,106,107,64,64,64,64,64,64,64,109,106,64,64,64,64,64, +64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,109,105,64,111,64,105,64,102,102,111,111,64,98,64,64,64,64,64,82,57,64,64,64,64,111,111,111,64,64,39,64,64,64,37,64,64,64,64,64,64,0,0,0,0,0,104,64,64,64,109,64,64,64,106,107,64,64,64,64,64,64,64,107,64,64,64,64,64,64, +44,64,64,64,64,64,64,64,64,64,117,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,102,64,111,64,64,64,64,111,64,64,111,98,111,107,64,59,64,64,64,64,64,64,107,107,64,111,64,54,64,64,64,37,64,64,64,64,64,64,64,0,0,0,87,0,0,64,64,64,109,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,100,64, +64,40,64,64,64,64,64,64,64,64,109,64,64,64,64,109,103,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,102,64,111,64,64,64,111,111,64,64,64,98,111,111,107,64,60,64,64,87,64,64,111,107,64,64,64,64,46,64,64,48,55,55,64,64,64,64,64,0,0,0,0,0,0,64,64,64,64,109,64,64,64,64,64,64,64,64,106,64,109,64,64,64,64,64,64,64, +1,56,64,109,64,64,64,64,64,64,109,64,64,64,64,109,64,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,64,64,64,111,64,64,64,64,111,111,64,64,64,64,111,64,64,64,64,64,64,58,111,64,64,64,64,136,54,64,64,64,43,47,56,64,64,64,64,64,0,0,0,0,0,0,64,64,64,64,87,64,64,64,64,64,64,64,109,109,109,64,64,64,64,64,169,64,64, +1,37,64,64,64,64,64,64,64,64,64,64,138,64,64,64,64,64,109,64,64,99,174,64,64,64,64,64,64,64,64,102,64,64,64,64,111,64,64,64,64,111,64,64,64,64,102,59,102,64,64,64,64,57,111,64,64,64,64,64,64,38,64,64,64,64,48,64,64,64,64,64,0,0,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,170,64, +37,64,122,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,64,173,64,64,64,64,64,64,64,64,64,64,64,64,64,64,111,64,64,64,107,111,64,64,107,64,102,60,64,64,107,64,64,111,64,64,64,64,64,64,64,42,64,64,64,64,56,64,64,64,64,64,0,0,0,0,0,0,64,64,64,64,64,64,64,175,64,175,64,64,87,64,64,64,64,64,64,64,64,171,64, +44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,106,64,64,64,172,64,64,64,64,64,64,99,64,64,64,64,64,133,64,111,98,64,64,64,107,64,64,64,102,64,64,64,64,64,64,64,121,64,64,64,64,64,107,64,35,64,64,64,64,37,64,64,64,64,64,0,0,0,0,0,0,64,174,64,64,64,64,64,175,174,64,175,64,64,64,64,64,64,64,64,64,64,64,64, +36,64,64,64,64,113,64,64,224,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,99,64,64,64,64,64,64,64,64,111,107,64,64,64,111,64,64,64,102,64,105,64,122,64,59,111,64,64,98,121,64,64,107,35,64,64,64,64,37,64,64,64,64,64,64,0,0,0,0,0,0,173,64,64,64,64,64,175,173,64,175,64,64,64,64,64,64,64,64,64,169,64,64,64, +63,36,64,64,64,64,64,64,64,64,64,64,64,35,36,64,64,64,64,64,99,64,64,64,64,99,64,64,64,64,64,64,64,64,64,64,121,107,64,64,64,64,111,64,64,102,111,105,64,64,64,64,60,64,64,98,98,64,102,64,54,64,64,64,64,48,64,64,64,64,64,64,0,0,0,0,100,0,172,64,64,64,64,64,175,172,64,64,64,64,64,175,176,64,64,64,64,64,170,64,64, +64,56,64,64,64,64,109,64,64,64,64,64,35,64,36,64,113,106,64,64,64,64,64,64,64,64,64,99,64,64,64,64,64,64,64,121,111,111,111,111,111,111,111,111,111,64,64,133,64,64,64,64,64,64,64,64,64,102,64,64,42,64,64,64,64,36,64,121,64,64,64,64,0,0,100,0,100,0,64,64,64,64,174,175,64,64,64,64,64,174,64,175,175,64,64,64,100,64,171,64,64, +64,44,64,64,64,64,64,109,64,64,64,64,35,64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,121,111,64,64,64,64,64,64,64,64,64,111,105,121,64,64,64,64,64,64,64,64,64,64,64,64,64,64,54,64,64,64,64,64,36,64,136,64,64,64,0,0,0,0,100,0,64,64,64,64,173,175,64,64,64,64,64,173,64,175,64,175,64,169,64,64,64,64,64, +64,36,64,64,64,64,64,64,64,64,64,35,64,64,64,52,64,64,64,64,64,64,64,64,64,64,99,64,64,64,107,64,64,105,64,64,64,64,64,64,64,64,111,102,64,121,64,64,58,64,59,64,64,64,64,64,64,64,64,64,42,64,64,64,64,64,36,0,0,0,0,64,0,100,0,0,0,0,64,64,64,172,175,64,64,64,64,64,172,64,64,64,64,175,64,170,64,64,64,64,64, +64,1,56,64,64,64,64,64,64,64,64,35,64,64,64,48,64,64,64,64,64,64,64,64,99,64,99,64,64,64,64,64,64,105,64,107,64,64,64,64,64,64,111,102,121,64,64,64,57,64,64,60,64,105,64,64,64,64,64,64,54,64,64,64,64,64,64,56,0,0,0,64,64,64,64,64,64,64,64,64,64,175,175,64,64,64,64,64,64,64,64,64,64,64,175,64,171,100,64,64,64, +1,44,64,64,212,64,64,64,64,64,35,64,64,64,64,40,64,64,64,64,64,64,99,99,64,64,64,64,64,64,64,109,111,105,111,111,64,64,64,64,111,111,64,102,121,64,64,64,64,64,64,64,105,107,107,64,64,64,64,64,34,64,64,64,64,41,48,64,0,0,0,64,64,64,64,64,64,64,64,64,174,175,64,100,64,64,64,174,64,64,100,64,169,64,175,64,64,64,64,64,64, +1,1,56,64,64,64,64,64,64,64,35,64,64,64,64,64,56,64,64,64,64,64,64,64,64,99,64,64,64,64,64,109,64,105,64,64,111,105,64,64,64,105,64,102,64,64,64,64,64,121,64,64,64,64,64,102,64,64,111,121,64,34,64,45,64,33,38,56,0,0,0,100,64,64,64,100,100,64,64,64,173,175,64,64,64,64,64,173,64,64,64,64,64,170,64,175,64,64,64,64,64, +1,37,64,64,64,64,117,64,39,47,64,64,64,64,64,48,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,105,64,64,64,105,64,64,64,105,105,102,64,64,64,64,64,64,64,64,64,64,64,102,64,64,64,64,64,64,34,37,38,37,64,53,64,0,0,0,64,64,64,64,64,64,64,64,172,64,64,64,64,100,64,172,64,64,64,64,64,64,171,64,175,175,64,64,64,64, +1,37,64,64,64,64,64,64,39,64,64,64,64,64,64,64,36,64,64,212,64,64,64,64,63,64,64,64,64,102,64,64,102,64,64,105,105,64,64,64,64,64,64,64,64,64,64,64,64,98,64,64,64,64,64,64,64,64,64,64,64,64,49,64,49,64,64,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,100,64,64,64,64,64,64,100,64,64,64,64,175,175,64,64,64, +37,64,138,64,64,64,64,39,64,64,64,64,64,64,64,64,36,64,64,64,64,64,64,64,64,102,109,109,109,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,121,64,64,64,64,64,64,64,64,64,64,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,100,64,64,64,64,169,64,64,64,64,64,64, +44,1,64,114,64,64,64,39,64,64,64,64,64,64,64,64,64,36,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,51,64,64,64,64,107,64,64,64,64,64,64,64,64,64,64,64,64,64,64,121,121,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,170,64,64,64,64,64, +40,1,64,64,134,64,39,64,64,64,64,64,64,64,64,64,64,36,64,64,64,64,64,39,40,64,102,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,51,35,43,52,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,171,64,64,64,64,64, +64,40,64,64,64,64,39,64,64,64,64,64,64,64,64,64,64,64,36,64,64,64,64,39,63,52,64,102,64,64,64,64,64,64,64,64,64,64,64,51,64,64,64,64,35,43,64,44,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,40,1,64,1,35,64,64,64,64,64,64,64,64,64,64,64,64,36,64,64,64,39,64,48,64,64,64,64,64,64,64,64,64,64,64,64,64,35,36,64,64,64,35,64,64,64,36,64,64,51,51,64,64,64,64,64,64,64,64,64,39,43,43,40,64,64,0,0,100,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,40,1,1,35,64,64,64,64,64,64,64,64,64,64,64,64,64,36,64,64,39,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,35,64,36,64,64,35,64,64,64,64,36,64,35,47,40,64,64,64,64,64,35,56,64,39,64,64,64,40,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,40,35,47,64,64,64,64,64,64,64,64,64,64,64,64,64,63,36,55,39,64,64,37,64,64,64,64,64,64,64,64,64,64,64,64,35,64,64,36,64,35,64,64,64,64,64,36,35,64,64,40,64,64,64,64,35,44,64,39,64,64,64,64,56,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,43,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,43,43,64,64,37,64,64,64,64,64,64,64,64,64,64,64,64,35,64,64,64,36,35,64,64,64,64,64,64,43,64,64,64,40,64,64,64,35,64,40,39,64,64,64,64,48,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,44,55,55,55,55,55,55,55,55,55,55,55,55,35,64,64,64,64,43,64,64,64,64,64,64,64,64,64,64,64,43,43,40,35,64,64,43,64,64,64,64,64,40,64,64,100,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, +64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,43,43,47,43,43,43,43,43,43,43,43,43,43,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,43,64,64,64,64,64,64,64,64,64,43,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V3/Content/Menu/Titel.png b/V3/Content/Menu/Titel.png new file mode 100644 index 0000000..d22295f Binary files /dev/null and b/V3/Content/Menu/Titel.png differ diff --git a/V3/Content/Menu/arrow_white.png b/V3/Content/Menu/arrow_white.png new file mode 100644 index 0000000..8e4d2e2 Binary files /dev/null and b/V3/Content/Menu/arrow_white.png differ diff --git a/V3/Content/Menu/mainscreen.jpg b/V3/Content/Menu/mainscreen.jpg new file mode 100644 index 0000000..654eaa6 Binary files /dev/null and b/V3/Content/Menu/mainscreen.jpg differ diff --git a/V3/Content/Sounds/Afraid_to_Go.mp3 b/V3/Content/Sounds/Afraid_to_Go.mp3 new file mode 100644 index 0000000..beb828b Binary files /dev/null and b/V3/Content/Sounds/Afraid_to_Go.mp3 differ diff --git a/V3/Content/Sounds/Knight.wav b/V3/Content/Sounds/Knight.wav new file mode 100644 index 0000000..cb088af Binary files /dev/null and b/V3/Content/Sounds/Knight.wav differ diff --git a/V3/Content/Sounds/Kosta_T_-_06.mp3 b/V3/Content/Sounds/Kosta_T_-_06.mp3 new file mode 100644 index 0000000..3d4ac62 Binary files /dev/null and b/V3/Content/Sounds/Kosta_T_-_06.mp3 differ diff --git a/V3/Content/Sounds/Monster_Gigante-Doberman-1334685792.wav b/V3/Content/Sounds/Monster_Gigante-Doberman-1334685792.wav new file mode 100644 index 0000000..4bfe6a4 Binary files /dev/null and b/V3/Content/Sounds/Monster_Gigante-Doberman-1334685792.wav differ diff --git a/V3/Content/Sounds/Mummy_Zombie-SoundBible.wav b/V3/Content/Sounds/Mummy_Zombie-SoundBible.wav new file mode 100644 index 0000000..cd3630c Binary files /dev/null and b/V3/Content/Sounds/Mummy_Zombie-SoundBible.wav differ diff --git a/V3/Content/Sounds/SkeletonHorse.wav b/V3/Content/Sounds/SkeletonHorse.wav new file mode 100644 index 0000000..7804c61 Binary files /dev/null and b/V3/Content/Sounds/SkeletonHorse.wav differ diff --git a/V3/Content/Sounds/explode.wav b/V3/Content/Sounds/explode.wav new file mode 100644 index 0000000..8c1d089 Binary files /dev/null and b/V3/Content/Sounds/explode.wav differ diff --git a/V3/Content/Sounds/explodemini.wav b/V3/Content/Sounds/explodemini.wav new file mode 100644 index 0000000..bcad45b Binary files /dev/null and b/V3/Content/Sounds/explodemini.wav differ diff --git a/V3/Content/Sounds/explosion1.ogg b/V3/Content/Sounds/explosion1.ogg new file mode 100644 index 0000000..64c1ab6 Binary files /dev/null and b/V3/Content/Sounds/explosion1.ogg differ diff --git a/V3/Content/Sounds/horse.wav b/V3/Content/Sounds/horse.wav new file mode 100644 index 0000000..5715ad1 Binary files /dev/null and b/V3/Content/Sounds/horse.wav differ diff --git a/V3/Content/Sounds/impactsplat01.ogg b/V3/Content/Sounds/impactsplat01.ogg new file mode 100644 index 0000000..731cf83 Binary files /dev/null and b/V3/Content/Sounds/impactsplat01.ogg differ diff --git a/V3/Content/Sounds/punch.wav b/V3/Content/Sounds/punch.wav new file mode 100644 index 0000000..395bb5c Binary files /dev/null and b/V3/Content/Sounds/punch.wav differ diff --git a/V3/Content/Sounds/walking.wav b/V3/Content/Sounds/walking.wav new file mode 100644 index 0000000..894dff4 Binary files /dev/null and b/V3/Content/Sounds/walking.wav differ diff --git a/V3/Content/Sounds/zonk2.wav b/V3/Content/Sounds/zonk2.wav new file mode 100644 index 0000000..77e37b4 Binary files /dev/null and b/V3/Content/Sounds/zonk2.wav differ diff --git a/V3/Content/Sources/Horse.blend b/V3/Content/Sources/Horse.blend new file mode 100644 index 0000000..017b12c Binary files /dev/null and b/V3/Content/Sources/Horse.blend differ diff --git a/V3/Content/Sources/Skeleton.blend b/V3/Content/Sources/Skeleton.blend new file mode 100644 index 0000000..0a8fd5d Binary files /dev/null and b/V3/Content/Sources/Skeleton.blend differ diff --git a/V3/Content/Sources/SkeletonHorse.blend b/V3/Content/Sources/SkeletonHorse.blend new file mode 100644 index 0000000..3520f1e Binary files /dev/null and b/V3/Content/Sources/SkeletonHorse.blend differ diff --git a/V3/Content/Sources/SkeletonHorse.png b/V3/Content/Sources/SkeletonHorse.png new file mode 100644 index 0000000..e0fc808 Binary files /dev/null and b/V3/Content/Sources/SkeletonHorse.png differ diff --git a/V3/Content/Sources/SkeletonRider.blend b/V3/Content/Sources/SkeletonRider.blend new file mode 100644 index 0000000..24d7161 Binary files /dev/null and b/V3/Content/Sources/SkeletonRider.blend differ diff --git a/V3/Content/Sources/SkeletonRider.png b/V3/Content/Sources/SkeletonRider.png new file mode 100644 index 0000000..681af75 Binary files /dev/null and b/V3/Content/Sources/SkeletonRider.png differ diff --git a/V3/Content/Sources/ZombieWithClub.png b/V3/Content/Sources/ZombieWithClub.png new file mode 100644 index 0000000..bea8eb3 Binary files /dev/null and b/V3/Content/Sources/ZombieWithClub.png differ diff --git a/V3/Content/Sources/castle.xcf b/V3/Content/Sources/castle.xcf new file mode 100644 index 0000000..50a7f8a Binary files /dev/null and b/V3/Content/Sources/castle.xcf differ diff --git a/V3/Content/Sources/create_spritesheet.sh b/V3/Content/Sources/create_spritesheet.sh new file mode 100644 index 0000000..eda0bd3 --- /dev/null +++ b/V3/Content/Sources/create_spritesheet.sh @@ -0,0 +1,7 @@ +#!/bin/bash +rows=8 # Possible directions (== 8 in isometric view) +columns=32 # Number of sprites per direction +cd out +montage *.png -mode concatenate -tile ${columns}x${rows} -background none out.png +mv out.png ../ +cd .. diff --git a/V3/Content/Sources/fleischklops.blend b/V3/Content/Sources/fleischklops.blend new file mode 100644 index 0000000..ce145da Binary files /dev/null and b/V3/Content/Sources/fleischklops.blend differ diff --git a/V3/Content/Sources/fleischklops.xcf b/V3/Content/Sources/fleischklops.xcf new file mode 100644 index 0000000..322f745 Binary files /dev/null and b/V3/Content/Sources/fleischklops.xcf differ diff --git a/V3/Content/Sources/horse_paint.png b/V3/Content/Sources/horse_paint.png new file mode 100644 index 0000000..74e4dd5 Binary files /dev/null and b/V3/Content/Sources/horse_paint.png differ diff --git a/V3/Content/Sources/horse_paint_sc.png b/V3/Content/Sources/horse_paint_sc.png new file mode 100644 index 0000000..453703a Binary files /dev/null and b/V3/Content/Sources/horse_paint_sc.png differ diff --git a/V3/Content/Sources/horse_tack.png b/V3/Content/Sources/horse_tack.png new file mode 100644 index 0000000..4f6a0b8 Binary files /dev/null and b/V3/Content/Sources/horse_tack.png differ diff --git a/V3/Content/Sources/houses_front.xcf b/V3/Content/Sources/houses_front.xcf new file mode 100644 index 0000000..680596d Binary files /dev/null and b/V3/Content/Sources/houses_front.xcf differ diff --git a/V3/Content/Sources/houses_rear.xcf b/V3/Content/Sources/houses_rear.xcf new file mode 100644 index 0000000..d711b47 Binary files /dev/null and b/V3/Content/Sources/houses_rear.xcf differ diff --git a/V3/Content/Sources/human_construction_set.xcf b/V3/Content/Sources/human_construction_set.xcf new file mode 100644 index 0000000..d0fb838 Binary files /dev/null and b/V3/Content/Sources/human_construction_set.xcf differ diff --git a/V3/Content/Sources/human_construction_set_female.xcf b/V3/Content/Sources/human_construction_set_female.xcf new file mode 100644 index 0000000..8c29a55 Binary files /dev/null and b/V3/Content/Sources/human_construction_set_female.xcf differ diff --git a/V3/Content/Sources/king.blend b/V3/Content/Sources/king.blend new file mode 100644 index 0000000..3bc5379 Binary files /dev/null and b/V3/Content/Sources/king.blend differ diff --git a/V3/Content/Sources/king_head.png b/V3/Content/Sources/king_head.png new file mode 100644 index 0000000..9bbc3c9 Binary files /dev/null and b/V3/Content/Sources/king_head.png differ diff --git a/V3/Content/Sources/necromancer.xcf b/V3/Content/Sources/necromancer.xcf new file mode 100644 index 0000000..dad43ad Binary files /dev/null and b/V3/Content/Sources/necromancer.xcf differ diff --git a/V3/Content/Sources/pathfinder.xcf b/V3/Content/Sources/pathfinder.xcf new file mode 100644 index 0000000..7833cea Binary files /dev/null and b/V3/Content/Sources/pathfinder.xcf differ diff --git a/V3/Content/Sources/prince.blend b/V3/Content/Sources/prince.blend new file mode 100644 index 0000000..c7c35a8 Binary files /dev/null and b/V3/Content/Sources/prince.blend differ diff --git a/V3/Content/Sources/prince.xcf b/V3/Content/Sources/prince.xcf new file mode 100644 index 0000000..14bbcf9 Binary files /dev/null and b/V3/Content/Sources/prince.xcf differ diff --git a/V3/Content/Sources/selection.xcf b/V3/Content/Sources/selection.xcf new file mode 100644 index 0000000..bbe3202 Binary files /dev/null and b/V3/Content/Sources/selection.xcf differ diff --git a/V3/Content/Sources/skeleton_horse.png b/V3/Content/Sources/skeleton_horse.png new file mode 100644 index 0000000..ed78f4a Binary files /dev/null and b/V3/Content/Sources/skeleton_horse.png differ diff --git a/V3/Content/Sources/the_triumph_of_death.jpg b/V3/Content/Sources/the_triumph_of_death.jpg new file mode 100644 index 0000000..654eaa6 Binary files /dev/null and b/V3/Content/Sources/the_triumph_of_death.jpg differ diff --git a/V3/Content/Sources/zombie.blend b/V3/Content/Sources/zombie.blend new file mode 100644 index 0000000..0ae1de3 Binary files /dev/null and b/V3/Content/Sources/zombie.blend differ diff --git a/V3/Content/Sprites/WhiteRectangle.png b/V3/Content/Sprites/WhiteRectangle.png new file mode 100644 index 0000000..7d3a386 Binary files /dev/null and b/V3/Content/Sprites/WhiteRectangle.png differ diff --git a/V3/Content/Sprites/arrows.png b/V3/Content/Sprites/arrows.png new file mode 100644 index 0000000..61a2db9 Binary files /dev/null and b/V3/Content/Sprites/arrows.png differ diff --git a/V3/Content/Sprites/buckler.png b/V3/Content/Sprites/buckler.png new file mode 100644 index 0000000..1253a60 Binary files /dev/null and b/V3/Content/Sprites/buckler.png differ diff --git a/V3/Content/Sprites/buckler_female.png b/V3/Content/Sprites/buckler_female.png new file mode 100644 index 0000000..3dd42a1 Binary files /dev/null and b/V3/Content/Sprites/buckler_female.png differ diff --git a/V3/Content/Sprites/chain.png b/V3/Content/Sprites/chain.png new file mode 100644 index 0000000..375f887 Binary files /dev/null and b/V3/Content/Sprites/chain.png differ diff --git a/V3/Content/Sprites/chain_female.png b/V3/Content/Sprites/chain_female.png new file mode 100644 index 0000000..e3b9c59 Binary files /dev/null and b/V3/Content/Sprites/chain_female.png differ diff --git a/V3/Content/Sprites/cloth.png b/V3/Content/Sprites/cloth.png new file mode 100644 index 0000000..3787867 Binary files /dev/null and b/V3/Content/Sprites/cloth.png differ diff --git a/V3/Content/Sprites/cloth_female.png b/V3/Content/Sprites/cloth_female.png new file mode 100644 index 0000000..f4d68b8 Binary files /dev/null and b/V3/Content/Sprites/cloth_female.png differ diff --git a/V3/Content/Sprites/cloud.png b/V3/Content/Sprites/cloud.png new file mode 100644 index 0000000..1e20701 Binary files /dev/null and b/V3/Content/Sprites/cloud.png differ diff --git a/V3/Content/Sprites/ellipse.png b/V3/Content/Sprites/ellipse.png new file mode 100644 index 0000000..c3e0c2c Binary files /dev/null and b/V3/Content/Sprites/ellipse.png differ diff --git a/V3/Content/Sprites/fleischklops.png b/V3/Content/Sprites/fleischklops.png new file mode 100644 index 0000000..b040c76 Binary files /dev/null and b/V3/Content/Sprites/fleischklops.png differ diff --git a/V3/Content/Sprites/fog.png b/V3/Content/Sprites/fog.png new file mode 100644 index 0000000..abb5572 Binary files /dev/null and b/V3/Content/Sprites/fog.png differ diff --git a/V3/Content/Sprites/head.png b/V3/Content/Sprites/head.png new file mode 100644 index 0000000..ff497fa Binary files /dev/null and b/V3/Content/Sprites/head.png differ diff --git a/V3/Content/Sprites/head_bald.png b/V3/Content/Sprites/head_bald.png new file mode 100644 index 0000000..51796a4 Binary files /dev/null and b/V3/Content/Sprites/head_bald.png differ diff --git a/V3/Content/Sprites/head_chain.png b/V3/Content/Sprites/head_chain.png new file mode 100644 index 0000000..9565715 Binary files /dev/null and b/V3/Content/Sprites/head_chain.png differ diff --git a/V3/Content/Sprites/head_chain_female.png b/V3/Content/Sprites/head_chain_female.png new file mode 100644 index 0000000..f016527 Binary files /dev/null and b/V3/Content/Sprites/head_chain_female.png differ diff --git a/V3/Content/Sprites/head_female.png b/V3/Content/Sprites/head_female.png new file mode 100644 index 0000000..3849fae Binary files /dev/null and b/V3/Content/Sprites/head_female.png differ diff --git a/V3/Content/Sprites/head_plate.png b/V3/Content/Sprites/head_plate.png new file mode 100644 index 0000000..5c7f5b7 Binary files /dev/null and b/V3/Content/Sprites/head_plate.png differ diff --git a/V3/Content/Sprites/head_plate_female.png b/V3/Content/Sprites/head_plate_female.png new file mode 100644 index 0000000..709d24e Binary files /dev/null and b/V3/Content/Sprites/head_plate_female.png differ diff --git a/V3/Content/Sprites/king.png b/V3/Content/Sprites/king.png new file mode 100644 index 0000000..18b5ea7 Binary files /dev/null and b/V3/Content/Sprites/king.png differ diff --git a/V3/Content/Sprites/longsword.png b/V3/Content/Sprites/longsword.png new file mode 100644 index 0000000..7e12f43 Binary files /dev/null and b/V3/Content/Sprites/longsword.png differ diff --git a/V3/Content/Sprites/longsword_female.png b/V3/Content/Sprites/longsword_female.png new file mode 100644 index 0000000..34f4480 Binary files /dev/null and b/V3/Content/Sprites/longsword_female.png differ diff --git a/V3/Content/Sprites/necromancer.png b/V3/Content/Sprites/necromancer.png new file mode 100644 index 0000000..65258d5 Binary files /dev/null and b/V3/Content/Sprites/necromancer.png differ diff --git a/V3/Content/Sprites/necromancer_female.png b/V3/Content/Sprites/necromancer_female.png new file mode 100644 index 0000000..6d34095 Binary files /dev/null and b/V3/Content/Sprites/necromancer_female.png differ diff --git a/V3/Content/Sprites/nude.png b/V3/Content/Sprites/nude.png new file mode 100644 index 0000000..88f1588 Binary files /dev/null and b/V3/Content/Sprites/nude.png differ diff --git a/V3/Content/Sprites/nude_female.png b/V3/Content/Sprites/nude_female.png new file mode 100644 index 0000000..fdd5b33 Binary files /dev/null and b/V3/Content/Sprites/nude_female.png differ diff --git a/V3/Content/Sprites/plate.png b/V3/Content/Sprites/plate.png new file mode 100644 index 0000000..f4d49c8 Binary files /dev/null and b/V3/Content/Sprites/plate.png differ diff --git a/V3/Content/Sprites/plate_female.png b/V3/Content/Sprites/plate_female.png new file mode 100644 index 0000000..570afff Binary files /dev/null and b/V3/Content/Sprites/plate_female.png differ diff --git a/V3/Content/Sprites/prince.png b/V3/Content/Sprites/prince.png new file mode 100644 index 0000000..9a8e5d9 Binary files /dev/null and b/V3/Content/Sprites/prince.png differ diff --git a/V3/Content/Sprites/selection.png b/V3/Content/Sprites/selection.png new file mode 100644 index 0000000..4ce0e93 Binary files /dev/null and b/V3/Content/Sprites/selection.png differ diff --git a/V3/Content/Sprites/shield.png b/V3/Content/Sprites/shield.png new file mode 100644 index 0000000..a5b1068 Binary files /dev/null and b/V3/Content/Sprites/shield.png differ diff --git a/V3/Content/Sprites/shield_female.png b/V3/Content/Sprites/shield_female.png new file mode 100644 index 0000000..d4b074b Binary files /dev/null and b/V3/Content/Sprites/shield_female.png differ diff --git a/V3/Content/Sprites/shortsword.png b/V3/Content/Sprites/shortsword.png new file mode 100644 index 0000000..e10adf8 Binary files /dev/null and b/V3/Content/Sprites/shortsword.png differ diff --git a/V3/Content/Sprites/shortsword_female.png b/V3/Content/Sprites/shortsword_female.png new file mode 100644 index 0000000..d1f097e Binary files /dev/null and b/V3/Content/Sprites/shortsword_female.png differ diff --git a/V3/Content/Sprites/skeleton.png b/V3/Content/Sprites/skeleton.png new file mode 100644 index 0000000..09d6464 Binary files /dev/null and b/V3/Content/Sprites/skeleton.png differ diff --git a/V3/Content/Sprites/skeleton_archer.png b/V3/Content/Sprites/skeleton_archer.png new file mode 100644 index 0000000..5bdbc02 Binary files /dev/null and b/V3/Content/Sprites/skeleton_archer.png differ diff --git a/V3/Content/Sprites/skeleton_elite.png b/V3/Content/Sprites/skeleton_elite.png new file mode 100644 index 0000000..982c031 Binary files /dev/null and b/V3/Content/Sprites/skeleton_elite.png differ diff --git a/V3/Content/Sprites/skeleton_horse.png b/V3/Content/Sprites/skeleton_horse.png new file mode 100644 index 0000000..e0fc808 Binary files /dev/null and b/V3/Content/Sprites/skeleton_horse.png differ diff --git a/V3/Content/Sprites/skeleton_rider.png b/V3/Content/Sprites/skeleton_rider.png new file mode 100644 index 0000000..681af75 Binary files /dev/null and b/V3/Content/Sprites/skeleton_rider.png differ diff --git a/V3/Content/Sprites/staff.png b/V3/Content/Sprites/staff.png new file mode 100644 index 0000000..0200876 Binary files /dev/null and b/V3/Content/Sprites/staff.png differ diff --git a/V3/Content/Sprites/staff_female.png b/V3/Content/Sprites/staff_female.png new file mode 100644 index 0000000..3a526d5 Binary files /dev/null and b/V3/Content/Sprites/staff_female.png differ diff --git a/V3/Content/Sprites/zombie.png b/V3/Content/Sprites/zombie.png new file mode 100644 index 0000000..a68091a Binary files /dev/null and b/V3/Content/Sprites/zombie.png differ diff --git a/V3/Content/Sprites/zombie_club.png b/V3/Content/Sprites/zombie_club.png new file mode 100644 index 0000000..bea8eb3 Binary files /dev/null and b/V3/Content/Sprites/zombie_club.png differ diff --git a/V3/Content/Textures/EmptyPixel.png b/V3/Content/Textures/EmptyPixel.png new file mode 100644 index 0000000..626a832 Binary files /dev/null and b/V3/Content/Textures/EmptyPixel.png differ diff --git a/V3/Content/Textures/castle.png b/V3/Content/Textures/castle.png new file mode 100644 index 0000000..e19dd45 Binary files /dev/null and b/V3/Content/Textures/castle.png differ diff --git a/V3/Content/Textures/grassland.png b/V3/Content/Textures/grassland.png new file mode 100644 index 0000000..0a56056 Binary files /dev/null and b/V3/Content/Textures/grassland.png differ diff --git a/V3/Content/Textures/grassland_trees.png b/V3/Content/Textures/grassland_trees.png new file mode 100644 index 0000000..b2bced3 Binary files /dev/null and b/V3/Content/Textures/grassland_trees.png differ diff --git a/V3/Content/Textures/grassland_water.png b/V3/Content/Textures/grassland_water.png new file mode 100644 index 0000000..2083506 Binary files /dev/null and b/V3/Content/Textures/grassland_water.png differ diff --git a/V3/Content/Textures/houses_front.png b/V3/Content/Textures/houses_front.png new file mode 100644 index 0000000..94513d4 Binary files /dev/null and b/V3/Content/Textures/houses_front.png differ diff --git a/V3/Content/Textures/houses_rear.png b/V3/Content/Textures/houses_rear.png new file mode 100644 index 0000000..64012e1 Binary files /dev/null and b/V3/Content/Textures/houses_rear.png differ diff --git a/V3/Content/Textures/medieval_building_tiles.png b/V3/Content/Textures/medieval_building_tiles.png new file mode 100644 index 0000000..154be4e Binary files /dev/null and b/V3/Content/Textures/medieval_building_tiles.png differ diff --git a/V3/Content/Textures/pathfinder.png b/V3/Content/Textures/pathfinder.png new file mode 100644 index 0000000..ae86dfb Binary files /dev/null and b/V3/Content/Textures/pathfinder.png differ diff --git a/V3/Data/DebugMode.cs b/V3/Data/DebugMode.cs new file mode 100644 index 0000000..b93ae7a --- /dev/null +++ b/V3/Data/DebugMode.cs @@ -0,0 +1,21 @@ +namespace V3.Data +{ + /// + /// A debug level that can be set by the player. + /// + public enum DebugMode + { + /// + /// Disable all debug utils. + /// + Off, + /// + /// Show the FPS counter. + /// + Fps, + /// + /// Show all debug information. + /// + Full + } +} diff --git a/V3/Data/GameState.cs b/V3/Data/GameState.cs new file mode 100644 index 0000000..b38ec46 --- /dev/null +++ b/V3/Data/GameState.cs @@ -0,0 +1,64 @@ +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using V3.AI; +using V3.Objects; + +namespace V3.Data +{ + /// + /// Stores the current state of the game (the data that must be stored in + /// a save game). All members should be public and serializable. + /// + [Serializable] + public sealed class GameState + { + public List mCreatures = new List(); + public List mFog = new List(); + public Vector2 mCameraPosition; + public AiState mAiState = AiState.Idle; + } + + public enum CreatureType + { + FemalePeasant, + King, + KingsGuard, + Knight, + MalePeasant, + Meatball, + Necromancer, + Prince, + Skeleton, + SkeletonHorse, + Zombie + } + + public sealed class CreatureData + { + public CreatureType Type { get; set; } + public int Id { get; set; } + public int Life { get; set; } + public int MaxLife { get; set; } + public int Attack { get; set; } + public TimeSpan Recovery { get; set; } + public bool IsUpgraded { get; set; } + public float PositionX { get; set; } + public float PositionY { get; set; } + public MovementDirection MovementDirection { get; set; } + public MovementState MovementState { get; set; } + public MovementData MovementData { get; set; } + public int IsAttackingId { get; set; } + public bool Mounted { get; set; } + public int SkeletonId { get; set; } + // IsAttackingBuilding + } + + public sealed class MovementData + { + public List Path { get; set; } + public int Step { get; set; } + public Vector2 LastMovement { get; set; } + public bool IsMoving { get; set; } + } +} diff --git a/V3/Data/IGameStateManager.cs b/V3/Data/IGameStateManager.cs new file mode 100644 index 0000000..3a7f901 --- /dev/null +++ b/V3/Data/IGameStateManager.cs @@ -0,0 +1,20 @@ +namespace V3.Data +{ + /// + /// Stores the current game state. + /// + public interface IGameStateManager + { + /// + /// Stores the current game state and returns it. + /// + /// the current game state + GameState GetGameState(); + + /// + /// Restores the given game state. + /// + /// the game state to restore + void LoadGameState(GameState gameState); + } +} diff --git a/V3/Data/IOptionsManager.cs b/V3/Data/IOptionsManager.cs new file mode 100644 index 0000000..6910107 --- /dev/null +++ b/V3/Data/IOptionsManager.cs @@ -0,0 +1,18 @@ +namespace V3.Data +{ + /// + /// Handles the storing and loading of game options to the hard disk. + /// + public interface IOptionsManager + { + /// + /// The current options. + /// + Options Options { get; } + + /// + /// Saves the current options to the hard disk. + /// + void SaveOptions(); + } +} diff --git a/V3/Data/IPathManager.cs b/V3/Data/IPathManager.cs new file mode 100644 index 0000000..5574b35 --- /dev/null +++ b/V3/Data/IPathManager.cs @@ -0,0 +1,30 @@ +namespace V3.Data +{ + /// + /// Provides access to the default applications path, i. e. the + /// directories where save games, achievements and other persistent data + /// can be stored. + /// + public interface IPathManager + { + /// + /// The base directory for persistent application data. + /// + string AppDirectory { get; } + + /// + /// The directory for save games. + /// + string SaveGameDirectory { get; } + + /// + /// The file to store the options in. + /// + string OptionsFile { get; } + + /// + /// Creates the application directories that do not already exist. + /// + void CreateMissingDirectories(); + } +} \ No newline at end of file diff --git a/V3/Data/ISaveGame.cs b/V3/Data/ISaveGame.cs new file mode 100644 index 0000000..6f954e1 --- /dev/null +++ b/V3/Data/ISaveGame.cs @@ -0,0 +1,25 @@ +using System; + +namespace V3.Data +{ + /// + /// Stores a game state with some metadata. + /// + public interface ISaveGame : IComparable + { + /// + /// The creation time of this save game in local time. + /// + DateTime Timestamp { get; set; } + + /// + /// The compability version of this save game. + /// + int Version { get; set; } + + /// + /// The data stored in this save game. + /// + GameState GameState { get; set; } + } +} \ No newline at end of file diff --git a/V3/Data/ISaveGameManager.cs b/V3/Data/ISaveGameManager.cs new file mode 100644 index 0000000..f4e810f --- /dev/null +++ b/V3/Data/ISaveGameManager.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace V3.Data +{ + /// + /// Stores and manages the game state in save games. + /// + public interface ISaveGameManager + { + /// + /// Creates and persists a new save game of the given data with the + /// title. + /// + /// the data to store + void CreateSaveGame(GameState gameState); + + /// + /// Loads all available save games and returns them ordered by the + /// creation date. + /// + /// a list of all available save games, orderd by creation + /// data + List GetSaveGames(); + } +} \ No newline at end of file diff --git a/V3/Data/Internal/GameStateManager.cs b/V3/Data/Internal/GameStateManager.cs new file mode 100644 index 0000000..53ef3de --- /dev/null +++ b/V3/Data/Internal/GameStateManager.cs @@ -0,0 +1,81 @@ +using System.Collections.Generic; +using V3.Camera; +using V3.Map; +using V3.Objects; + +namespace V3.Data.Internal +{ + /// + /// Default implementation of IGameStateManager. + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class GameStateManager : IGameStateManager + { + private readonly CameraManager mCameraManager; + private readonly CreatureFactory mCreatureFactory; + private readonly IMapManager mMapManager; + private readonly IObjectsManager mObjectsManager; + + public GameStateManager(CameraManager cameraManager, CreatureFactory creatureFactory, + IMapManager mapManager, IObjectsManager objectsManager) + { + mCameraManager = cameraManager; + mCreatureFactory = creatureFactory; + mMapManager = mapManager; + mObjectsManager = objectsManager; + } + + /// + /// Restores the given game state. + /// + public GameState GetGameState() + { + var gameState = new GameState(); + foreach (var obj in mObjectsManager.CreatureList) + { + gameState.mCreatures.Add(obj.SaveData()); + } + gameState.mCameraPosition = mCameraManager.GetCamera().Location; + return gameState; + } + + /// + /// Restores the given game state. + /// + /// the game state to restore + public void LoadGameState(GameState gameState) + { + mObjectsManager.Clear(); + mObjectsManager.ImportMapObjects(mMapManager.GetObjects()); + var creatures = new Dictionary(); + + // load creatures + foreach (var creatureData in gameState.mCreatures) + { + ICreature creature = mCreatureFactory.CreateCreature(creatureData.Type, creatureData.Id); + if (creature == null) + continue; + creature.LoadData(creatureData); + if (creature is Necromancer) + mObjectsManager.CreatePlayerCharacter((Necromancer) creature); + else if (creature is King) // || creature is Prince + mObjectsManager.CreateBoss(creature); + else + mObjectsManager.CreateCreature(creature); + + creatures.Add(creature.Id, creature); + } + + // fix references + foreach (var creatureData in gameState.mCreatures) + { + if (!creatures.ContainsKey(creatureData.Id)) + continue; + creatures[creatureData.Id].LoadReferences(creatureData, creatures); + } + + if (mCameraManager.GetCamera() is CameraScrolling) + mCameraManager.GetCamera().Location = gameState.mCameraPosition; + } + } +} diff --git a/V3/Data/Internal/OptionsManager.cs b/V3/Data/Internal/OptionsManager.cs new file mode 100644 index 0000000..d581ba5 --- /dev/null +++ b/V3/Data/Internal/OptionsManager.cs @@ -0,0 +1,65 @@ +using System.IO; +using System.Runtime.Serialization; +using System.Xml.Serialization; +using Ninject; + +namespace V3.Data.Internal +{ + /// + /// Default implementation of IOptionsManager. + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class OptionsManager : IOptionsManager, IInitializable + { + /// + /// The current options. + /// + public Options Options { get; private set; } + + private readonly IPathManager mPathManager; + private readonly XmlSerializer mSerializer = new XmlSerializer(typeof(Options)); + + /// + /// Creates a new OptionsManager. + /// + public OptionsManager(IPathManager pathManager) + { + mPathManager = pathManager; + } + + public void Initialize() + { + Options = LoadOptions(); + } + + /// + /// Saves the current options to the hard disk. + /// + public void SaveOptions() + { + var stream = new FileStream(mPathManager.OptionsFile, FileMode.Create, FileAccess.Write); + mSerializer.Serialize(stream, Options); + stream.Close(); + } + + private Options LoadOptions() + { + if (!File.Exists(mPathManager.OptionsFile)) + return new Options(); + var stream = new FileStream(mPathManager.OptionsFile, FileMode.Open, FileAccess.Read); + try + { + return (Options)mSerializer.Deserialize(stream); + } + catch (SerializationException) + { + // ignore so far + } + finally + { + stream.Close(); + } + return new Options(); + } + } +} diff --git a/V3/Data/Internal/PathManager.cs b/V3/Data/Internal/PathManager.cs new file mode 100644 index 0000000..3f4ad9d --- /dev/null +++ b/V3/Data/Internal/PathManager.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; + +namespace V3.Data.Internal { + /// + /// Default implementation of IPathManager. + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class PathManager : IPathManager + { + /// + /// The base directory for persistent application data. + /// + public string AppDirectory { get; } + + /// + /// The file to store the options in. + /// + public string OptionsFile { get; } + + /// + /// The directory for save games. + /// + public string SaveGameDirectory { get; } + + /// + /// Creates a new path manager and initializes the paths, but does not + /// create the directories if they don’t already exist. + /// + public PathManager() + { + var localAppDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + AppDirectory = $"{localAppDir}/V3"; + SaveGameDirectory = $"{AppDirectory}/SaveGames"; + OptionsFile = $"{AppDirectory}/Options.xml"; + } + + /// + /// Creates the application directories that do not already exist. + /// + public void CreateMissingDirectories() + { + string[] directories = { AppDirectory, SaveGameDirectory }; + foreach (var directory in directories) + { + if (!Directory.Exists(directory)) + Directory.CreateDirectory(directory); + } + } + } +} diff --git a/V3/Data/Internal/SaveGame.cs b/V3/Data/Internal/SaveGame.cs new file mode 100644 index 0000000..9ff3586 --- /dev/null +++ b/V3/Data/Internal/SaveGame.cs @@ -0,0 +1,65 @@ +using System; + +namespace V3.Data.Internal +{ + // TODO: once the game state is getting larger, we have to separate the + // save game metadata from the game state. + + /// + /// A save game that has a timestamp and a title, and that can store + /// the game state. + /// + [Serializable] + public sealed class SaveGame : ISaveGame + { + /// + /// The creation time of this save game in local time. + /// + public DateTime Timestamp { get; set; } + + /// + /// The compability version of this save game. + /// + public int Version { get; set; } + + /// + /// The data stored in this save game. + /// + public GameState GameState { get; set; } + + /// + /// Empty constructor for serialization. + /// + private SaveGame() + { + } + + /// + /// Creates a new save game from the given data. + /// + /// the creation time of the save game + /// the compability version of the save game + /// the game state to store in the save game + internal SaveGame(DateTime timestamp, int version, GameState gameState) + { + Timestamp = timestamp; + Version = version; + GameState = gameState; + } + + /// + /// Compares this save game object to another save game object based + /// on the creation time. + /// + /// the save game to compare this save game + /// with + /// a value less than zero if this save game has been saved + /// before the given save game, zero if they have been saved at the + /// same time and a value greater than zero if the given save game has + /// been saved before the given one + public int CompareTo(ISaveGame saveGame) + { + return Timestamp.CompareTo(saveGame.Timestamp); + } + } +} diff --git a/V3/Data/Internal/SaveGameManager.cs b/V3/Data/Internal/SaveGameManager.cs new file mode 100644 index 0000000..1c52b50 --- /dev/null +++ b/V3/Data/Internal/SaveGameManager.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Xml.Serialization; + +namespace V3.Data.Internal +{ + /// + /// Default implementation if ISaveGameManager. + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class SaveGameManager : ISaveGameManager + { + private readonly IPathManager mPathManager; + + private const int CurrentVersion = 1; + private readonly XmlSerializer mFormatter = new XmlSerializer(typeof(SaveGame)); + + /// + /// Creates a new SaveGameManager. The save game directory must already + /// be created. + /// + public SaveGameManager(IPathManager pathManager) + { + mPathManager = pathManager; + } + + /// + /// Creates and persists a new save game of the given data with the + /// title. + /// + /// the data to store + public void CreateSaveGame(GameState gameState) + { + var saveGame = new SaveGame(DateTime.Now, CurrentVersion, gameState); + var fileName = GetUniqueFileName(); + var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write); + mFormatter.Serialize(stream, saveGame); + stream.Close(); + } + + /// + /// Loads all available save games and returns them ordered by the + /// creation date. + /// + /// a list of all available save games, orderd by creation + /// data + public List GetSaveGames() + { + var saveGames = new List(); + foreach (var file in Directory.GetFiles(mPathManager.SaveGameDirectory)) + { + var stream = new FileStream(file, FileMode.Open, FileAccess.Read); + try + { + var saveGame = (ISaveGame)mFormatter.Deserialize(stream); + if (saveGame.Version == CurrentVersion) + saveGames.Add(saveGame); + } + catch (SerializationException) + { + // ignore so far + } + stream.Close(); + } + saveGames.Sort(); + return saveGames; + } + + private string GetUniqueFileName() + { + var index = 1; + var fileName = GetFileName(index); + while (File.Exists(fileName)) + { + index++; + fileName = GetFileName(index); + } + return fileName; + } + + private string GetFileName(int index) + { + return $"{mPathManager.SaveGameDirectory}/{index:000}.xml"; + } + } +} diff --git a/V3/Data/Options.cs b/V3/Data/Options.cs new file mode 100644 index 0000000..38670dc --- /dev/null +++ b/V3/Data/Options.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using V3.Camera; + +namespace V3.Data +{ + /// + /// The graphics options. + /// + [Serializable] + public sealed class Options + { + /// + /// All available screen resolutions. + /// + public static List Resolutions { get; } = new List + { + new Point(800, 480), + new Point(800, 600), + new Point(1024, 768), + new Point(1280, 800), + new Point(1280, 1024), + new Point(1366, 768), + new Point(1920, 1080) + }; + + /// + /// All available camera types. + /// + public static List CameraTypes { get; } = + Enum.GetValues(typeof (CameraType)).Cast().ToList(); + + /// + /// All available debug modes. + /// + public static List DebugModes { get; } = + Enum.GetValues(typeof (DebugMode)).Cast().ToList(); + + /// + /// All available volume settings. + /// + public static List Volumes { get; } = new List() + { + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 80, + 90, + 100 + }; + private static readonly Point sDefaultResolution = Resolutions[0]; + private static readonly bool sDefaultIsFullScreen = false; + private static readonly DebugMode sDefaultDebugMode = DebugMode.Off; + private static readonly CameraType sDefaultCameraType = CameraType.Scrolling; + private static readonly bool sDefaultIsMuted = false; + private static readonly int sDefaultVolume = 100; + + /// + /// The current screen resolution. + /// + public Point Resolution { get; set; } = sDefaultResolution; + + /// + /// True if the game should be run in full screen, otherwise false. + /// + public bool IsFullScreen { get; set; } = sDefaultIsFullScreen; + + /// + /// The current debug mode. + /// + public DebugMode DebugMode { get; set; } = sDefaultDebugMode; + + /// + /// The current camera type. + /// + public CameraType CameraType { get; set; } = sDefaultCameraType; + + /// + /// True if the sound is muted, otherwise false. + /// + public bool IsMuted { get; set; } = sDefaultIsMuted; + + /// + /// The volume to use for the sound (if the sound is not muted), range + /// 0 .. 100. + /// + public int Volume { get; set; } = sDefaultVolume; + + /// + /// Returns the effective volume with regard to the mute and volume + /// settings. + /// + /// the effective volume that should be used for sound + public float GetEffectiveVolume() + { + return IsMuted ? 0 : ((float) Volume) / 100; + } + } +} diff --git a/V3/Effects/AbstractEffect.cs b/V3/Effects/AbstractEffect.cs new file mode 100644 index 0000000..c3468c0 --- /dev/null +++ b/V3/Effects/AbstractEffect.cs @@ -0,0 +1,74 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Data; + +namespace V3.Effects +{ + public abstract class AbstractEffect : IEffect + { + private Texture2D mTexture; + private int mSpritesPerRow; + private int mTotalSprites; + private int mAnimationState; + private Rectangle mAnimationRectangle; + private SoundEffect mSoundEffect; + private SoundEffectInstance mSoundEffectInstance; + + public bool IsPlaying { get; private set; } + protected virtual UpdatesPerSecond UpdatesPerSecond { get; } = new UpdatesPerSecond(24); + protected abstract string TextureFile { get; } + protected virtual Point SpriteSize { get; } = new Point(128, 128); + protected virtual string SoundFile { get; } = String.Empty; + + public void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Effects/" + TextureFile); + mSpritesPerRow = mTexture.Width / SpriteSize.X; + mTotalSprites = mSpritesPerRow * (mTexture.Height / SpriteSize.Y); + if (SoundFile.Length != 0) + { + mSoundEffect = contentManager.Load("Sounds/" + SoundFile); + mSoundEffectInstance = mSoundEffect.CreateInstance(); + } + } + + public void PlayOnce(Point position, Point size, IOptionsManager optionsManager) + { + mAnimationRectangle = new Rectangle(position - size / new Point(2, 2), size); + IsPlaying = true; + if (SoundFile.Length != 0) + { + mSoundEffectInstance.Volume = optionsManager.Options.GetEffectiveVolume(); + mSoundEffectInstance.Play(); + } + } + + public void Update(GameTime gameTime) + { + if (!IsPlaying) return; + if (UpdatesPerSecond.IsItTime(gameTime)) + { + if (mAnimationState < mTotalSprites) + { + mAnimationState++; + } + else + { + mAnimationState = 0; + IsPlaying = false; + } + } + } + + public void Draw(SpriteBatch spriteBatch) + { + if (!IsPlaying) return; + spriteBatch.Draw(mTexture, mAnimationRectangle, + new Rectangle(new Point(mAnimationState % mSpritesPerRow * SpriteSize.X, mAnimationState / mSpritesPerRow * SpriteSize.Y), SpriteSize), + Color.White); + } + } +} \ No newline at end of file diff --git a/V3/Effects/BloodBang.cs b/V3/Effects/BloodBang.cs new file mode 100644 index 0000000..f5e1f3c --- /dev/null +++ b/V3/Effects/BloodBang.cs @@ -0,0 +1,8 @@ +namespace V3.Effects +{ + public class BloodBang : AbstractEffect + { + protected override string TextureFile { get; } = "blood_hit_04"; + protected override string SoundFile { get; } = "impactsplat01"; + } +} \ No newline at end of file diff --git a/V3/Effects/BloodExplosion.cs b/V3/Effects/BloodExplosion.cs new file mode 100644 index 0000000..baa38d4 --- /dev/null +++ b/V3/Effects/BloodExplosion.cs @@ -0,0 +1,11 @@ +namespace V3.Effects +{ + /// + /// A round explosion of blood. + /// + public sealed class BloodExplosion : AbstractEffect + { + protected override string TextureFile { get; } = "blood_hit_08"; + protected override string SoundFile { get; } = "impactsplat01"; + } +} \ No newline at end of file diff --git a/V3/Effects/BloodFountain.cs b/V3/Effects/BloodFountain.cs new file mode 100644 index 0000000..5684e34 --- /dev/null +++ b/V3/Effects/BloodFountain.cs @@ -0,0 +1,11 @@ +namespace V3.Effects +{ + /// + /// A small fountain of blood. + /// + public sealed class BloodFountain : AbstractEffect + { + protected override string TextureFile { get; } = "blood_hit_02"; + protected override string SoundFile { get; } = "impactsplat01"; + } +} \ No newline at end of file diff --git a/V3/Effects/EffectsManager.cs b/V3/Effects/EffectsManager.cs new file mode 100644 index 0000000..a175e34 --- /dev/null +++ b/V3/Effects/EffectsManager.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Data; + +namespace V3.Effects +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class EffectsManager : IEffectsManager + { + private readonly ContentManager mContentManager; + private readonly IOptionsManager mOptionsManager; + private readonly List mActiveEffects = new List(); + + public EffectsManager(ContentManager contentManager, IOptionsManager optionsManager) + { + mContentManager = contentManager; + mOptionsManager = optionsManager; + } + + public void Update(GameTime gameTime) + { + var doneEffects = new List(); + foreach (var effect in mActiveEffects) + { + effect.Update(gameTime); + if (!effect.IsPlaying) + { + doneEffects.Add(effect); + } + } + foreach (var doneEffect in doneEffects) + { + mActiveEffects.Remove(doneEffect); + } + } + + public void Draw(SpriteBatch spriteBatch) + { + foreach (var effect in mActiveEffects) + { + effect.Draw(spriteBatch); + } + } + + public void PlayOnce(IEffect effect, Point position, Point size) + { + effect.LoadContent(mContentManager); + mActiveEffects.Add(effect); + effect.PlayOnce(position, size, mOptionsManager); + } + } +} \ No newline at end of file diff --git a/V3/Effects/Explosion.cs b/V3/Effects/Explosion.cs new file mode 100644 index 0000000..afcfdf4 --- /dev/null +++ b/V3/Effects/Explosion.cs @@ -0,0 +1,14 @@ +using Microsoft.Xna.Framework; + +namespace V3.Effects +{ + /// + /// A large explosion with sound. + /// + public class Explosion : AbstractEffect + { + protected override string TextureFile { get; } = "explosion"; + protected override Point SpriteSize { get; } = new Point(320, 240); + protected override string SoundFile { get; } = "explosion1"; + } +} \ No newline at end of file diff --git a/V3/Effects/HorseEffect.cs b/V3/Effects/HorseEffect.cs new file mode 100644 index 0000000..a09fe60 --- /dev/null +++ b/V3/Effects/HorseEffect.cs @@ -0,0 +1,11 @@ +using Microsoft.Xna.Framework; + +namespace V3.Effects +{ + public sealed class HorseEffect : AbstractEffect + { + protected override string TextureFile { get; } = "quake"; + protected override Point SpriteSize { get; } = new Point(256, 128); + protected override string SoundFile { get; } = "horse"; + } +} diff --git a/V3/Effects/IEffect.cs b/V3/Effects/IEffect.cs new file mode 100644 index 0000000..73cf1ef --- /dev/null +++ b/V3/Effects/IEffect.cs @@ -0,0 +1,44 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Data; + +namespace V3.Effects +{ + /// + /// Interface for a single effect. + /// + public interface IEffect + { + /// + /// Is the effect playing at the moment? + /// + bool IsPlaying { get; } + + /// + /// Play the specific effect once, do not loop. + /// + /// Position where effect should be played. Points to the middle of the effect animation. + /// Size of the effect. + /// For checking the volume of the sound if there is one. + void PlayOnce(Point position, Point size, IOptionsManager optionsManager); + + /// + /// Update the effect. + /// + /// Game time used for checking animation duration. + void Update(GameTime gameTime); + + /// + /// Draw the effect. + /// + /// Sprite batch used. + void Draw(SpriteBatch spriteBatch); + + /// + /// Load graphics and possibly sound for the effect. + /// + /// Content manager used. + void LoadContent(ContentManager contentManager); + } +} \ No newline at end of file diff --git a/V3/Effects/IEffectsManager.cs b/V3/Effects/IEffectsManager.cs new file mode 100644 index 0000000..3ea6154 --- /dev/null +++ b/V3/Effects/IEffectsManager.cs @@ -0,0 +1,31 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Effects +{ + /// + /// Interface for managing visual effects like explosions and stuff. + /// + public interface IEffectsManager + { + /// + /// Update all effects. + /// + /// Game time used for calculation effects duration. + void Update(GameTime gameTime); + + /// + /// Draw all effects. + /// + /// Sprite batch used. + void Draw(SpriteBatch spriteBatch); + + /// + /// Play an effect once, then delete it. + /// + /// Which effect to play. + /// Position where effect should be played. Points to the middle of the effect animation. + /// Size of the effect. + void PlayOnce(IEffect effect, Point position, Point size); + } +} \ No newline at end of file diff --git a/V3/Effects/Quake.cs b/V3/Effects/Quake.cs new file mode 100644 index 0000000..c08825d --- /dev/null +++ b/V3/Effects/Quake.cs @@ -0,0 +1,11 @@ +using Microsoft.Xna.Framework; + +namespace V3.Effects +{ + public class Quake : AbstractEffect + { + protected override string TextureFile { get; } = "quake"; + protected override Point SpriteSize { get; } = new Point(256, 128); + protected override string SoundFile { get; } = "explodemini"; + } +} \ No newline at end of file diff --git a/V3/Effects/SmokeBig.cs b/V3/Effects/SmokeBig.cs new file mode 100644 index 0000000..3dfce2a --- /dev/null +++ b/V3/Effects/SmokeBig.cs @@ -0,0 +1,10 @@ +namespace V3.Effects +{ + /// + /// A large ring of smoke, spreading over some area. + /// + public sealed class SmokeBig : AbstractEffect + { + protected override string TextureFile { get; } = "particlefx_03"; + } +} \ No newline at end of file diff --git a/V3/Effects/SmokeMedium.cs b/V3/Effects/SmokeMedium.cs new file mode 100644 index 0000000..09447fa --- /dev/null +++ b/V3/Effects/SmokeMedium.cs @@ -0,0 +1,13 @@ +using System.Diagnostics.CodeAnalysis; + +namespace V3.Effects +{ + /// + /// A medium sized ring of smoke, spreading over some area. + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public sealed class SmokeMedium : AbstractEffect + { + protected override string TextureFile { get; } = "particlefx_04"; + } +} \ No newline at end of file diff --git a/V3/Effects/SmokeSmall.cs b/V3/Effects/SmokeSmall.cs new file mode 100644 index 0000000..f2f2dce --- /dev/null +++ b/V3/Effects/SmokeSmall.cs @@ -0,0 +1,10 @@ +namespace V3.Effects +{ + /// + /// A small ring of smoke, spreading over some area. + /// + public sealed class SmokeSmall : AbstractEffect + { + protected override string TextureFile { get; } = "particlefx_05"; + } +} \ No newline at end of file diff --git a/V3/Ellipse.cs b/V3/Ellipse.cs new file mode 100644 index 0000000..076aff0 --- /dev/null +++ b/V3/Ellipse.cs @@ -0,0 +1,31 @@ +using System; +using Microsoft.Xna.Framework; + +namespace V3 +{ + public struct Ellipse + { + private Vector2 Center { get; } + private float Width { get; } + private float Height { get; } + + public Rectangle BoundaryRectangle => new Rectangle((Center - new Vector2(Width / 2, Height / 2)).ToPoint(), new Vector2(Width, Height).ToPoint()); + + internal Ellipse(Vector2 center, float width, float height) + { + Center = center; + Width = width; + Height = height; + } + + internal bool Contains(Vector2 position) + { + if (Math.Pow(position.X - Center.X, 2) / Math.Pow(Width/2, 2) + + Math.Pow(position.Y - Center.Y, 2) / Math.Pow(Height/2, 2) <= 1) + { + return true; + } + return false; + } + } +} diff --git a/V3/Faction.cs b/V3/Faction.cs new file mode 100644 index 0000000..96b2f9b --- /dev/null +++ b/V3/Faction.cs @@ -0,0 +1,7 @@ +namespace V3 +{ + public enum Faction + { + Undead, Kingdom, Plebs + } +} \ No newline at end of file diff --git a/V3/Icon.ico b/V3/Icon.ico new file mode 100644 index 0000000..38c64b5 Binary files /dev/null and b/V3/Icon.ico differ diff --git a/V3/Input/IInputManager.cs b/V3/Input/IInputManager.cs new file mode 100644 index 0000000..b092ebb --- /dev/null +++ b/V3/Input/IInputManager.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace V3.Input +{ + /// + /// Watches the state of the mouse and keyboard and creates events if a + /// change (key pressed or released) is detected. To use this class, call + /// Update in every update round. After the update, you may access the + /// generated events in KeyEvents and MouseEvents. The input manager only + /// watches the mouse buttons and keys listed in sWatchedKeys and + /// sWatchedButtons. + /// + public interface IInputManager + { + /// + /// The key events that were generated during the last update. Reset + /// in the next update. + /// + ICollection KeyEvents { get; } + + /// + /// The mouse events that were generated during the last update. Reset in + /// the next update. + /// + ICollection MouseEvents { get; } + + /// + /// Updates the keyboard and mouse status and generates the key and mouse + /// events in KeyEvents and MouseEvents if changes were detected. Should + /// be called once every update, before doing something else. + /// + void Update(); + } +} \ No newline at end of file diff --git a/V3/Input/IKeyEvent.cs b/V3/Input/IKeyEvent.cs new file mode 100644 index 0000000..42b99c6 --- /dev/null +++ b/V3/Input/IKeyEvent.cs @@ -0,0 +1,20 @@ +using Microsoft.Xna.Framework.Input; + +namespace V3.Input +{ + /// + /// An event that is triggered if a key is pressed or released on the + /// keyboard. + /// + public interface IKeyEvent + { + /// + /// The key that was pressed or released. + /// + Keys Key { get; } + /// + /// The type of the event (key pressed or released?). + /// + KeyState KeyState { get; } + } +} \ No newline at end of file diff --git a/V3/Input/IMouseEvent.cs b/V3/Input/IMouseEvent.cs new file mode 100644 index 0000000..37b221d --- /dev/null +++ b/V3/Input/IMouseEvent.cs @@ -0,0 +1,34 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace V3.Input +{ + /// + /// An event that is sent when a mouse button is pressed or released. + /// + public interface IMouseEvent + { + /// + /// The mouse button that was pressed or released. + /// + MouseButton MouseButton { get; } + /// + /// The state of the mouse button (pressed or released?). + /// + ButtonState ButtonState { get; } + /// + /// The position where the mouse button was pressed the last time. + /// + Point PositionPressed { get; } + /// + /// The position where the mouse button was released if this is a + /// release event, null otherwise. + /// + Point? PositionReleased { get; } + /// + /// True if PositionReleased is a valid on-screen position, otherwise + /// false. + /// + bool ReleasedOnScreen { get; } + } +} diff --git a/V3/Input/IMouseEventHandler.cs b/V3/Input/IMouseEventHandler.cs new file mode 100644 index 0000000..7c8701c --- /dev/null +++ b/V3/Input/IMouseEventHandler.cs @@ -0,0 +1,14 @@ +namespace V3.Input +{ + /// + /// Handles mouse events. + /// + public interface IMouseEventHandler + { + /// + /// Handle the given mouse event, if applicable. + /// + /// the mouse event to handle + void HandleMouseEvent(IMouseEvent mouseEvent); + } +} diff --git a/V3/Input/Internal/InputManager.cs b/V3/Input/Internal/InputManager.cs new file mode 100644 index 0000000..8e6ce2e --- /dev/null +++ b/V3/Input/Internal/InputManager.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using Ninject; + +namespace V3.Input.Internal +{ + /// + /// Watches the state of the mouse and keyboard and creates events if a + /// change (key pressed or released) is detected. To use this class, call + /// Update in every update round. After the update, you may access the + /// generated events in KeyEvents and MouseEvents. The input manager only + /// watches the mouse buttons and keys listed in sWatchedKeys and + /// sWatchedButtons. + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal sealed class InputManager : IInputManager, IInitializable + { + /// + /// The key events that were generated during the last update. Reset + /// in the next update. + /// + public ICollection KeyEvents { get; } = new HashSet(); + /// + /// The mouse events that were generated during the last update. Reset in + /// the next update. + /// + public ICollection MouseEvents { get; } = new HashSet(); + + private static readonly ICollection sWatchedKeys = new List { Keys.Enter, Keys.Escape, Keys.E, Keys.L, Keys.Q, Keys.S, Keys.F1, Keys.F2 , Keys.F3, Keys.F4, Keys.F5, Keys.F6, Keys.F7, Keys.F8 }; + + private static readonly ICollection sWatchedButtons = new List { MouseButton.Left, MouseButton.Right, MouseButton.Middle }; + + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + + private readonly IDictionary mKeyStates = new Dictionary(); + + private readonly IDictionary mButtonStates = new Dictionary(); + + private readonly IDictionary mButtonPositions = new Dictionary(); + + /// + /// Creates a new input manager. + /// + public InputManager(GraphicsDeviceManager graphicsDeviceManager) + { + mGraphicsDeviceManager = graphicsDeviceManager; + } + + public void Initialize() + { + foreach (var key in sWatchedKeys) + mKeyStates.Add(key, KeyState.Up); + foreach (var button in sWatchedButtons) + { + mButtonStates.Add(button, ButtonState.Released); + mButtonPositions.Add(button, null); + } + } + + /// + /// Updates the keyboard and mouse status and generates the key and mouse + /// events in KeyEvents and MouseEvents if changes were detected. Should + /// be called once every update, before doing something else. + /// + public void Update() + { + UpdateKeyboard(); + UpdateMouse(); + } + + private void UpdateKeyboard() + { + KeyEvents.Clear(); + + var state = Keyboard.GetState(); + foreach (var key in sWatchedKeys) + { + var newState = state[key]; + if (newState != mKeyStates[key]) + { + mKeyStates[key] = newState; + KeyEvents.Add(new KeyEvent(key, newState)); + } + } + } + + private void UpdateMouse() + { + MouseEvents.Clear(); + + var state = Mouse.GetState(); + foreach (var button in sWatchedButtons) + { + var newState = GetButtonState(state, button); + if (newState != mButtonStates[button]) + { + var position = new Point(state.X, state.Y); + var positionPressed = position; + Point? positionReleased = null; + if (newState == ButtonState.Released) + { + if (mButtonPositions[button].HasValue) + positionPressed = mButtonPositions[button].Value; + positionReleased = position; + } + + mButtonStates[button] = newState; + mButtonPositions[button] = position; + + var releasedOnScreen = false; + if (positionReleased.HasValue) + releasedOnScreen = IsPointOnScreen(positionReleased.Value); + + MouseEvents.Add(new MouseEvent(button, newState, positionPressed, positionReleased, releasedOnScreen)); + } + } + } + + private bool IsPointOnScreen(Point point) + { + var viewport = mGraphicsDeviceManager.GraphicsDevice.Viewport; + return point.X >= 0 && point.X <= viewport.Width && point.Y >= 0 && point.Y <= viewport.Height; + } + + private static ButtonState GetButtonState(MouseState state, MouseButton button) + { + switch (button) + { + case MouseButton.Left: + return state.LeftButton; + case MouseButton.Right: + return state.RightButton; + case MouseButton.Middle: + return state.MiddleButton; + default: + return state.LeftButton; + } + } + } +} diff --git a/V3/Input/Internal/KeyEvent.cs b/V3/Input/Internal/KeyEvent.cs new file mode 100644 index 0000000..b4a450e --- /dev/null +++ b/V3/Input/Internal/KeyEvent.cs @@ -0,0 +1,32 @@ +using Microsoft.Xna.Framework.Input; + +namespace V3.Input.Internal +{ + /// + /// Default implementation of an event that is triggered if a key is + /// pressed or released on the keyboard. + /// + internal sealed class KeyEvent : IKeyEvent + { + /// + /// The key that was pressed or released. + /// + public Keys Key { get; } + /// + /// The type of the event (key pressed or released?). + /// + public KeyState KeyState { get; } + + /// + /// Creates a new key event with the given data. + /// + /// the key that was pressed or released + /// the type of the event (presesd or + /// released?) + public KeyEvent(Keys key, KeyState keyState) + { + Key = key; + KeyState = keyState; + } + } +} diff --git a/V3/Input/Internal/MouseEvent.cs b/V3/Input/Internal/MouseEvent.cs new file mode 100644 index 0000000..f8024aa --- /dev/null +++ b/V3/Input/Internal/MouseEvent.cs @@ -0,0 +1,57 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; + +namespace V3.Input.Internal +{ + /// + /// Default implementation of an event that is sent when a mouse button is + /// pressed or released. + /// + internal sealed class MouseEvent : IMouseEvent + { + /// + /// The mouse button that was pressed or released. + /// + public MouseButton MouseButton { get; } + /// + /// The state of the mouse button (pressed or released?). + /// + public ButtonState ButtonState { get; } + /// + /// The position where the mouse button was pressed the last time. + /// + public Point PositionPressed { get; } + /// + /// The position where the mouse button was released if this is a + /// release event, null otherwise. + /// + public Point? PositionReleased { get; } + /// + /// True if PositionReleased is a valid on-screen position, otherwise + /// false. + /// + public bool ReleasedOnScreen { get; } + + /// + /// Creates a new mouse event with the given data. + /// + /// the mouse button that was pressed or + /// released + /// the type of the event (pressed or + /// released?) + /// the position of the last press of + /// the button + /// the position of the release of the + /// button if this is a release event, or null otherwise + /// true if positionReleased is a valid + /// on-screen position. + public MouseEvent(MouseButton mouseButton, ButtonState buttonState, Point positionPressed, Point? positionReleased, bool releasedOnScreen) + { + MouseButton = mouseButton; + ButtonState = buttonState; + PositionPressed = positionPressed; + PositionReleased = positionReleased; + ReleasedOnScreen = releasedOnScreen; + } + } +} diff --git a/V3/Input/MouseButton.cs b/V3/Input/MouseButton.cs new file mode 100644 index 0000000..616872b --- /dev/null +++ b/V3/Input/MouseButton.cs @@ -0,0 +1,9 @@ +namespace V3.Input +{ + public enum MouseButton + { + Left, + Right, + Middle + } +} diff --git a/V3/Map/AbstractLayer.cs b/V3/Map/AbstractLayer.cs new file mode 100644 index 0000000..efc626d --- /dev/null +++ b/V3/Map/AbstractLayer.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Objects; + +namespace V3.Map +{ + /// + /// A drawable map layer usually created from a Tiled map file. + /// + public abstract class AbstractLayer + { + private const int CellHeight = Constants.CellHeight; + private const int CellWidth = Constants.CellWidth; + + private readonly int mTileWidth; + private readonly int mTileHeight; + private readonly int mMapWidth; + private readonly int mMapHeight; + private readonly List mTextureObjects = new List(); + private readonly int[,] mTileArray; + private readonly SortedList mTilesets; + + protected AbstractLayer(int tileWidth, + int tileHeight, + int mapWidth, + int mapHeight, + int[,] tileArray, + SortedList tilesets) + { + mTileWidth = tileWidth; + mTileHeight = tileHeight; + mMapWidth = mapWidth; + mMapHeight = mapHeight; + mTilesets = tilesets; + if (tileArray.Length == mapWidth * mapHeight) + { + mTileArray = tileArray; + } + else + { + throw new Exception("Error constructing map layer. Map size does not fit the map description."); + } + } + + /// + /// Create the map objects according to the given map array. + /// + public void CreateObjects() + { + var firstgridList = mTilesets.Keys; + for (int i = 0; i < mMapHeight; i++) + { + int horizontalOffset = (i % 2 == 0) ? (-mTileWidth / 2) : 0; + for (int j = 0; j < mMapWidth; j++) + { + int tileId = mTileArray[i, j]; + // Checks which tileset needs to be used for the specific tile ID at position [i, j] + for (int k = firstgridList.Count - 1; k >= 0; k--) + { + if (tileId == 0) + { + // This does generally nothing. But you can overwrite GenerateNullObject() for other behaviour. + TextureObject objectToInsert = GenerateNullObject(); + if (objectToInsert != null) + { + mTextureObjects.Add(objectToInsert); + } + break; + } + else if (tileId >= firstgridList[k]) + { + Tileset tileset = mTilesets.Values[k]; + int firstgrid = firstgridList[k]; + Point position = SelectPosition(j, i, horizontalOffset); + Point textureSize = new Point(tileset.TileWidth, tileset.TileHeight); + Point destination = SelectDestination(j, i, horizontalOffset, tileset.OffsetX, tileset.TileHeight, tileset.OffsetY); + Point source = SelectSource(tileId, firstgrid, tileset.TileWidth, tileset.TileHeight, tileset.Columns); + IGameObject objectToInsert; + if (tileset.Name == "houses_rear" || tileset.Name == "houses_front") + { + if (source.Y < textureSize.Y * 2) + { + int initialDamage = 0; + if (source.X / textureSize.X == 1) + { + initialDamage = 50; + } + else if (source.X / textureSize.X == 2) + { + initialDamage = 80; + } + IBuilding building = new Woodhouse(position.ToVector2(), new Rectangle(destination, textureSize), tileset.Name, source.Y % 384 == 0 ? BuildingFace.SW : BuildingFace.NO); + building.TakeDamage(initialDamage); + objectToInsert = building; + } + else + { + int initialDamage = 0; + if (source.X / textureSize.X == 1) + { + initialDamage = 60; + } + else if (source.X / textureSize.X == 2) + { + initialDamage = 100; + } + IBuilding building = new Forge(position.ToVector2(), new Rectangle(destination, textureSize), tileset.Name, source.Y % 384 == 0 ? BuildingFace.SW : BuildingFace.NO); + building.TakeDamage(initialDamage); + objectToInsert = building; + } + } + else if (tileset.Name == "castle") + { + IBuilding building = new Objects.Castle(position.ToVector2(), new Rectangle(destination, textureSize), tileset.Name, BuildingFace.SW); + objectToInsert = building; + } + else + { + objectToInsert = new TextureObject(position, + destination, + textureSize, + source, + tileset.Name); + } + mTextureObjects.Add(objectToInsert); + break; + } + } + } + } + } + + protected virtual TextureObject GenerateNullObject() + { + return null; + } + + /// + /// Loads the image files needed for drawing the tilesets. + /// + /// Content manager used for loading the ressources. + public void LoadContent(ContentManager contentManager) + { + mTextureObjects.ForEach(o => o.LoadContent(contentManager)); + } + + /// + /// Draws only the parts of the map which are visible. More efficient than the other Draw-Method. + /// Not very robust and maybe does not work correctly most layers. + /// This is because of gaps in the list of game objects. + /// + /// Sprite batch used. + /// Needed to tell which objects of the map are looked upon. + public void Draw(SpriteBatch spriteBatch, ICamera camera) + { + int tilesHorizontal = camera.ScreenSize.X / mTileWidth; + int tilesVertical = camera.ScreenSize.Y * 2 / mTileHeight; + int horizontalStart = camera.ScreenRectangle.X / mTileWidth; + int verticalStart = camera.ScreenRectangle.Y * 2 / mTileHeight; + /* + for (int i = 0; i < tilesVertical; i++) + { + for (int j = 0; j < tilesHorizontal; j++) + { + mTextureObjects[horizontalStart + j].Draw(spriteBatch); + } + } + */ + for (int j = 0; j < tilesVertical + 2; j++) + { + for (int i = 0; i < tilesHorizontal + 2; i++) + { + int index = i + horizontalStart + (j + verticalStart) * mMapWidth; + if (index < mTextureObjects.Count) + { + mTextureObjects[index].Draw(spriteBatch); + } + } + } + } + + /// + /// Extract a collision grid from the map layer. Used in pathfinding. + /// + /// A two dimensional boolean collision grid. + public bool[,] ExtractCollisions() + { + int gridHeight = (mMapHeight - 1) * mTileHeight/ CellHeight / 2; + int gridWidth = (mMapWidth - 1) * mTileWidth / CellWidth; + bool[,] collisionGrid = new bool[gridHeight, gridWidth]; + var firstgridList = mTilesets.Keys; + for (int i = 0; i < mMapHeight; i++) + { + for (int j = 0; j < mMapWidth; j++) + { + int tileId = mTileArray[i, j]; + for (int k = firstgridList.Count - 1; k >= 0; k--) + { + if (tileId >= firstgridList[k]) + { + Tileset tileset = mTilesets.Values[k]; + int firstgrid = firstgridList[k]; + tileId -= firstgrid; + bool[,] collisionData; + // Is there even collision data for the specific tile ID? + if (tileset.TileCollisions.TryGetValue(tileId, out collisionData)) + { + int cellOffset = (i % 2 == 0 ? -mTileWidth / 2 : 0) / CellWidth; + int cellsHorizontal = mTileWidth / CellWidth; + int cellsVertical = mTileHeight / CellHeight; + int iStart = (i - 1) * cellsVertical / 2 + cellsVertical - tileset.CollisionHeight + tileset.OffsetY / CellHeight; + int jStart = j * cellsHorizontal + cellOffset + tileset.OffsetX / CellWidth; + for (int iData = 0; iData < tileset.CollisionHeight; iData++) + { + for (int jData = 0; jData < tileset.CollisionWidth; jData++) + { + // Do we even need to update collisionGrid? + if (iStart + iData >= 0 && iStart + iData < gridHeight && jStart + jData >= 0 && jStart + jData < gridWidth && + collisionData[iData, jData] && !collisionGrid[iStart + iData, jStart + jData]) + { + collisionGrid[iStart + iData, jStart + jData] = collisionData[iData, jData]; + } + } + } + } + break; + } + } + } + } + return collisionGrid; + } + + public List ExtractObjects() + { + return mTextureObjects; + } + + private Point SelectDestination(int x, int y, int xOffset, int tileXOffset, int tileHeight, int tileYOffset) + { + return new Point(x * mTileWidth + xOffset + tileXOffset, + (y - 1) * (mTileHeight / 2) - tileHeight + mTileHeight + tileYOffset); + } + + private Point SelectSource(int tileId, int firstgrid, int tileWidth, int tileHeight, int tilesPerRow) + { + return new Point((tileId - firstgrid) % tilesPerRow * tileWidth, (tileId - firstgrid) / tilesPerRow * tileHeight); + } + + private Point SelectPosition(int x, int y, int xOffset) + { + return new Point(x * mTileWidth + xOffset + mTileWidth / 2, y * (mTileHeight / 2)); + } + } +} \ No newline at end of file diff --git a/V3/Map/Area.cs b/V3/Map/Area.cs new file mode 100644 index 0000000..5712c6e --- /dev/null +++ b/V3/Map/Area.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using V3.Objects; + +namespace V3.Map +{ + public enum AreaType + { + Village, // has no soldiers or knights, only peasants + Castle, // many knights patrolling around + Graveyard // here you can respawn zombies + } + + /// + /// Holding area data of the map. Later used for generating enemies. + /// + public sealed class Area + { + private const int DistanceHorizontal = 64; + private const int DistanceVertical = 32; + private readonly AreaType mType; + private Rectangle mArea; + private readonly double mDensity; + private readonly double mChance; + + /// + /// Gets the area type. + /// + public AreaType Type => mType; + + /// + /// Creates a new area for generating population. + /// + /// Which type of area. Determines which population is spawned. + /// The size and position of the area. + /// The population density. Together with chance. + /// The chance that a creature is actually created. + /// Name of the area as shown in the game. + // ReSharper disable once UnusedParameter.Local + public Area(string type, Rectangle data, double density = 0d, double chance = 0d, string name = "") + { + switch (type) + { + case "village": + mType = AreaType.Village; + break; + case "castle": + mType = AreaType.Castle; + break; + case "graveyard": + mType = AreaType.Graveyard; + break; + default: + throw new Exception("Error parsing the map. There is no behaviour defined for objects of type " + type + "."); + } + if (density > 1d || chance > 1d || density < 0d || chance < 0d) + { + throw new Exception("Error when parsing area data from map. Density and/or chance is not in range 0.0 to 1.0."); + } + mArea = data; + mDensity = density; + mChance = chance; + } + + /// + /// Creates the initial population for this area. + /// + /// The factory used for creating creatures. + /// Used for checking collisions when creating population. + /// + public List GetPopulation(CreatureFactory creatureFactory, Pathfinder pathfinder) + { + var population = new List(); + if (mDensity <= 0) return population; // Catch division by zero. + var rndInt = new Random(); + var rnd = new Random(); + for (double i = DistanceVertical / mDensity + mArea.Y; i < mArea.Height + mArea.Y; i += DistanceVertical / mDensity ) + { + for (double j = DistanceHorizontal / mDensity + mArea.X; j < mArea.Width + mArea.X; j += DistanceHorizontal / mDensity ) + { + if (mChance < rnd.NextDouble()) continue; + var position = new Vector2((float) j, (float) i); + if (mType == AreaType.Village) + { + ICreature peasant; + if (rnd.NextDouble() < 0.5d) + { + peasant = creatureFactory.CreateMalePeasant(position, (MovementDirection)rndInt.Next(8)); + } + else + { + peasant = creatureFactory.CreateFemalePeasant(position, (MovementDirection)rndInt.Next(8)); + } + if (!pathfinder.AllWalkable(peasant.BoundaryRectangle)) continue; + population.Add(peasant); + } + else if (mType == AreaType.Castle) + { + ICreature guard = creatureFactory.CreateKingsGuard(position, (MovementDirection)rndInt.Next(8)); + if (!pathfinder.AllWalkable(guard.BoundaryRectangle)) continue; + population.Add(guard); + } + } + } + return population; + } + + /// + /// Is a given creature standing in the area? + /// + /// Check for this creature. + /// + public bool Contains(ICreature creature) + { + return mArea.Contains(creature.Position.ToPoint()); + } + } +} \ No newline at end of file diff --git a/V3/Map/Constants.cs b/V3/Map/Constants.cs new file mode 100644 index 0000000..2de2e25 --- /dev/null +++ b/V3/Map/Constants.cs @@ -0,0 +1,12 @@ +namespace V3.Map +{ + /// + /// Constants for describing the size of the cells of the collision grid. + /// Important for pathfinding. + /// + public static class Constants + { + public const int CellHeight = 16; + public const int CellWidth = 16; + } +} \ No newline at end of file diff --git a/V3/Map/FloorLayer.cs b/V3/Map/FloorLayer.cs new file mode 100644 index 0000000..ebe05f0 --- /dev/null +++ b/V3/Map/FloorLayer.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using V3.Objects; + +namespace V3.Map +{ + /// + /// The floor of the map consisting of the ground to walk on, grass or water. + /// + public sealed class FloorLayer : AbstractLayer + { + public FloorLayer(int tileWidth, int tileHeight, int mapWidth, int mapHeight, int[,] tileArray, SortedList tilesets) + : base(tileWidth, tileHeight, mapWidth, mapHeight, tileArray, tilesets) + { + } + + protected override TextureObject GenerateNullObject() + { + return new TextureObject(); + } + } +} diff --git a/V3/Map/FogOfWar.cs b/V3/Map/FogOfWar.cs new file mode 100644 index 0000000..a243b60 --- /dev/null +++ b/V3/Map/FogOfWar.cs @@ -0,0 +1,107 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Objects; + +namespace V3.Map +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class FogOfWar + { + private const int FogRange = 64; + private const int SightRadius = 1000; + private Point mMapSize; + private Texture2D mFog; + private readonly List mFogRectangle = new List(); + + /// + /// Get the size of the map and create an boolean array + /// + /// the size of the map + public void LoadGrid(Point size) + { + mMapSize = size; + CreateArray(); + } + + /// + /// An array so save whether the sprites already walked on this area + /// + private void CreateArray() + { + for (int i = -FogRange; i < mMapSize.Y; i += FogRange) + { + for (int j = -FogRange * 2; j < mMapSize.X; j += FogRange) + { + mFogRectangle.Add(new Rectangle(j, i, mFog.Width, mFog.Height)); + } + } + } + + /// + /// The position from creatures which can open the fog + /// + /// creatures which are able to open the fog + public void Update(ICreature creature) + { + Ellipse creatureEllipse = new Ellipse(creature.Position, SightRadius, SightRadius); + var markedForDeletion = new List(); + foreach (var fog in mFogRectangle) + { + if (!creature.IsDead && creatureEllipse.Contains(fog.Center.ToVector2())) + { + markedForDeletion.Add(fog); + } + } + foreach (var fogToDelete in markedForDeletion) + { + mFogRectangle.Remove(fogToDelete); + } + } + + /// + /// The sprite for the fog + /// + /// + public void LoadContent(ContentManager content) + { + mFog = content.Load("Sprites/cloud"); + } + + /// + /// Try to draw fog of war efficiently. + /// + /// Sprite batch used. + public void DrawFog(SpriteBatch spriteBatch) + { + /* + var screen = camera.ScreenRectangle; + int fogPerRow = (mMapSize.X + FogRange) / FogRange; + int fogPerColumn = (mMapSize.Y + FogRange) / FogRange; + for (int i = screen.Y / FogRange; i < (screen.Y + screen.Height) / FogRange; i++) + { + for (int j = screen.X / FogRange; j < (screen.X + screen.Width) / FogRange; j++) + { + spriteBatch.Draw(mFog, mFogRectangle[i * fogPerRow], Color.Black); + } + } + */ + foreach (var fog in mFogRectangle) + { + spriteBatch.Draw(mFog, fog, Color.Black); + } + } + + public void SetFog(List fog) + { + mFogRectangle.Clear(); + mFogRectangle.AddRange(fog); + } + + public List GetFog() + { + return mFogRectangle; + } + } +} diff --git a/V3/Map/IMapManager.cs b/V3/Map/IMapManager.cs new file mode 100644 index 0000000..9333d63 --- /dev/null +++ b/V3/Map/IMapManager.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Objects; + +namespace V3.Map +{ + /// + /// Manager for loading and drawing game maps. Also holds information about map attributes. + /// + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public interface IMapManager + { + /// + /// A list of map areas (rectangle-sized). + /// + List Areas { get; } + + /// + /// Size of the shown map in pixels. + /// + Point SizeInPixel { get; } + /// + /// Size of the map in tiles. (Some tiles are cut off at the edges.) + /// + Point SizeInTiles { get; } + /// + /// Size of a single tile in pixels. + /// + Point TileSize { get; } + /// + /// Number of cells the pathfinding grid consists of. + /// + Point PathfindingGridSize { get; } + /// + /// Size of a single cell of the pathfinding grid in pixels. + /// + Point PathfindingCellSize { get; } + /// + /// File name of the loaded map (without suffix). + /// + string FileName { get; } + /// + /// Efficiently draw the floor layer. Only draw the tiles seen by the camera. + /// + /// + /// + void DrawFloor(SpriteBatch spriteBatch, ICamera camera); + /// + /// Load a map file and create the map layers and pathfinding information. + /// + /// Name of the map file (without suffix). + void Load(string fileName); + /// + /// Returns all objects in the objects layer. + /// + /// List of all static game objects imported from the map. + List GetObjects(); + /// + /// Returns the pathfinding grid for passing to the pathfinder. + /// + /// A grid used for pathfinding. + PathfindingGrid GetPathfindingGrid(); + /// + /// Efficiently draw the pathfinding grid. For debugging purposes. + /// + /// Sprite batch used. + /// Current camera for calculating the shown screen. + void DrawPathfindingGrid(SpriteBatch spriteBatch, ICamera camera); + + /// + /// Draws the minimap to specified position. + /// + /// Sprite batch used. + /// Where to draw the minimap and which size. + void DrawMinimap(SpriteBatch spriteBatch, Rectangle position); + + /// + /// Automatically creates an initial population from the map data and returns it. + /// + /// Factory for creating creatues. + /// Pathfinder is used for checking collisions when creating creatures. + /// Initial population in a list. + List GetPopulation(CreatureFactory creatureFactory, Pathfinder pathfinder); + } +} \ No newline at end of file diff --git a/V3/Map/MapManager.cs b/V3/Map/MapManager.cs new file mode 100644 index 0000000..f62278c --- /dev/null +++ b/V3/Map/MapManager.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Objects; + +namespace V3.Map +{ + // ReSharper disable once ClassNeverInstantiated.Global + public class MapManager : IMapManager + { + private TiledParser mTiledParser; + private FloorLayer mFloorLayer; + private ObjectLayer mObjectLayer; + private List mAreas; + private PathfindingGrid mPathfindingGrid; + private readonly ContentManager mContentManager; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + + public List Areas => mAreas; + + public Point SizeInPixel { get; private set; } + public Point SizeInTiles { get; private set; } + public Point TileSize { get; private set; } + public Point PathfindingGridSize { get; private set; } + public Point PathfindingCellSize { get; private set; } + public string FileName { get; private set; } + + public MapManager(ContentManager contentManager, GraphicsDeviceManager graphicsDeviceManager) + { + mContentManager = contentManager; + mGraphicsDeviceManager = graphicsDeviceManager; + } + + public void DrawFloor(SpriteBatch spriteBatch, ICamera camera) + { + mFloorLayer.Draw(spriteBatch, camera); + } + + public void Load(string fileName) + { + mTiledParser = new TiledParser(); + // Parse map data. + mTiledParser.Parse(fileName); + FileName = fileName; + TileSize = new Point(mTiledParser.TileWidth, mTiledParser.TileHeight); + SizeInTiles = new Point(mTiledParser.MapWidth, mTiledParser.MapHeight); + SizeInPixel = new Point((SizeInTiles.X - 1) * TileSize.X, SizeInTiles.Y / 2 * TileSize.Y - TileSize.Y / 2); + // Create floor layer of the map. + mFloorLayer = new FloorLayer(mTiledParser.TileWidth, mTiledParser.TileHeight, mTiledParser.MapWidth, mTiledParser.MapHeight, mTiledParser.MapLayers[0], mTiledParser.TileSets); + mFloorLayer.CreateObjects(); + mFloorLayer.LoadContent(mContentManager); + // Create object layer of the map. + mObjectLayer = new ObjectLayer(mTiledParser.TileWidth, mTiledParser.TileHeight, mTiledParser.MapWidth, mTiledParser.MapHeight, mTiledParser.MapLayers[1], mTiledParser.TileSets); + mObjectLayer.CreateObjects(); + mObjectLayer.LoadContent(mContentManager); + // Get areas from the map + mAreas = mTiledParser.Areas; + // Create pathfinding grid used in the pathfinder. + mPathfindingGrid = new PathfindingGrid(mTiledParser.MapWidth, mTiledParser.MapHeight, mTiledParser.TileWidth, mTiledParser.TileHeight); + mPathfindingGrid.LoadContent(mContentManager); + mPathfindingGrid.CreateCollisions(mFloorLayer.ExtractCollisions()); + mPathfindingGrid.CreateCollisions(mObjectLayer.ExtractCollisions()); + PathfindingGridSize = new Point(mPathfindingGrid.mGridWidth, mPathfindingGrid.mGridHeight); + PathfindingCellSize = new Point(Constants.CellWidth, Constants.CellHeight); + // Create Minimap texture from pathfinding grid. + mPathfindingGrid.CreateMinimap(mGraphicsDeviceManager.GraphicsDevice); + } + + public List GetObjects() + { + return mObjectLayer.ExtractObjects(); + } + + public List GetPopulation(CreatureFactory creatureFactory, Pathfinder pathfinder) + { + return mAreas.SelectMany(area => area.GetPopulation(creatureFactory, pathfinder)).ToList(); + } + + public PathfindingGrid GetPathfindingGrid() + { + return mPathfindingGrid; + } + + public void DrawPathfindingGrid(SpriteBatch spriteBatch, ICamera camera) + { + mPathfindingGrid.Draw(spriteBatch, camera); + } + + public void DrawMinimap(SpriteBatch spriteBatch, Rectangle position) + { + mPathfindingGrid.DrawSmallGrid(spriteBatch, position); + } + } +} \ No newline at end of file diff --git a/V3/Map/ObjectLayer.cs b/V3/Map/ObjectLayer.cs new file mode 100644 index 0000000..0e9d13c --- /dev/null +++ b/V3/Map/ObjectLayer.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace V3.Map +{ + /// + /// The map objects which are the same layer as the moving creatutes. + /// Buildings, flowers, trees etc. + /// + public sealed class ObjectLayer : AbstractLayer + { + public ObjectLayer(int tileWidth, int tileHeight, int mapWidth, int mapHeight, int[,] tileArray, SortedList tilesets) + : base(tileWidth, tileHeight, mapWidth, mapHeight, tileArray, tilesets) + { + } + } +} \ No newline at end of file diff --git a/V3/Map/Pathfinder.cs b/V3/Map/Pathfinder.cs new file mode 100644 index 0000000..3874d0b --- /dev/null +++ b/V3/Map/Pathfinder.cs @@ -0,0 +1,455 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; + +namespace V3.Map +{ + // ReSharper disable once ClassNeverInstantiated.Global + public class Pathfinder + { + private const int CellHeight = Constants.CellHeight; + private const int CellWidth = Constants.CellWidth; + + // An array of walkable search nodes + private SearchNode[,] mSearchNodes; + + // The width of the map + private int mLevelWidth; + + // the height of the map + private int mLevelHeight; + + // List for nodes that are available to search + private readonly List mOpenList = new List(); + + // List for nodes that are NOT available to search + private readonly List mClosedList = new List(); + + //Calculates the distance between two (vector)points + private float Heuristic(Vector2 position, Vector2 goal) + { + return (goal - position).Length(); // Manhattan distance + } + + public void LoadGrid(PathfindingGrid map) + { + mLevelWidth = map.mGridWidth; + mLevelHeight = map.mGridHeight; + InitializeSearchNodes(map); + } + + private void InitializeSearchNodes(PathfindingGrid map) + { + mSearchNodes = new SearchNode[mLevelWidth, mLevelHeight]; + + // Creates a searchnode for each tile + for (int x = 0; x < mLevelWidth; x++) + { + for (int y = 0; y < mLevelHeight; y++) + { + SearchNode node = new SearchNode(); + + node.mPosition = new Vector2(x, y); + + // Walk only on walkable tiles + node.mWalkable = map.GetIndex(x, y) == 0; + + // Stores nodes that can be walked on + if (node.mWalkable) + { + node.mNeighbors = new SearchNode[4]; + mSearchNodes[x, y] = node; + } + } + } + + for (int x = 0; x < mLevelWidth; x++) + { + for (int y = 0; y < mLevelHeight; y++) + { + SearchNode node = mSearchNodes[x, y]; + + // Note only walkable nodes + if (node == null || node.mWalkable == false) + continue; + + + // The neighbors for every node + Vector2[] neighbors = + { + new Vector2(x, y - 1), // Node above the current + new Vector2(x, y + 1), // Node below the current + new Vector2(x - 1, y), // Node to the left + new Vector2(x + 1, y) // Node to the right + }; + + for (int i = 0; i < neighbors.Length; i++) + { + Vector2 position = neighbors[i]; + + // Test whether this neighbor is part of the map + if (position.X < 0 || position.X > mLevelWidth - 1 || position.Y < 0 || + position.Y > mLevelHeight - 1) + continue; + + SearchNode neighbor = mSearchNodes[(int)position.X, (int)position.Y]; + + // Keep a reference to the nodes that can be walked on + if (neighbor == null || neighbor.mWalkable == false) + continue; + + // A reference to the neighbor + node.mNeighbors[i] = neighbor; + } + } + } + } + + // Reset the state of the search node + private void ResetSearchNodes() + { + mOpenList.Clear(); + mClosedList.Clear(); + + for (int x = 0; x < mLevelWidth; x++) + { + for (int y = 0; y < mLevelHeight; y++) + { + SearchNode node = mSearchNodes[x, y]; + + if (node == null) + continue; + + node.mInOpenList = false; + node.mInClosedList = false; + node.mDistanceTraveled = float.MaxValue; + node.mDistanceToGoal = float.MaxValue; + } + } + } + + // Returns the node with the smallest distance + private SearchNode FindBestNode() + { + SearchNode currentTile = mOpenList[0]; + + float smallestDistanceToGoal = float.MaxValue; + + // Find the closest node to the goal + for (int i = 0; i < mOpenList.Count; i++) + { + if (mOpenList[i].mDistanceToGoal < smallestDistanceToGoal) + { + currentTile = mOpenList[i]; + smallestDistanceToGoal = currentTile.mDistanceToGoal; + } + } + return currentTile; + } + + // Use parent field to trace a path from search node to start node + private List FindFinalPath(SearchNode startNode, SearchNode endNode) + { + int counter = 0; + + if (startNode == endNode) + { + return new List(); + } + + mClosedList.Add(endNode); + + SearchNode parentTile = endNode.mParent; + + // Find the best path + while (parentTile != startNode) + { + mClosedList.Add(parentTile); + parentTile = parentTile.mParent; + } + + // Path from position to goal (from tile to tile) + List betaPath = new List(); + + // Final path after RayCasting + List finalPath = new List(); + + // Reverse the path and transform into the map + for (int i = mClosedList.Count - 1; i >= 0; i--) + { + betaPath.Add(new Vector2(mClosedList[i].mPosition.X * CellWidth + 8, mClosedList[i].mPosition.Y * CellHeight + 8)); + } + + // Short the path via RayCasting + for (int i = 1; i < betaPath.Count;) + { + if (!RayCast(betaPath[counter], betaPath[i])) + { + finalPath.Add(betaPath[i - 1]); + counter = i - 1; + } + else + { + i++; + } + } + finalPath.Add(betaPath[betaPath.Count - 1]); + return finalPath; + } + + //Test Points + private Vector2 CheckStartNode(Vector2 startNode) + { + var start = startNode; + + var startXPos = startNode; + var startXNeg = startNode; + var startYPos = startNode; + var startYNeg = startNode; + + // When sprite is blocked out of map, he returns to the edge of the map + if (startNode.X > mLevelWidth - 2) + startNode.X = mLevelWidth - 2; + if (startNode.X < 2) + startNode.X = 2; + if (startNode.Y < 4) + startNode.Y = 4; + if (startNode.Y > mLevelHeight - 2) + startNode.Y = mLevelHeight - 2; + + // When sprite stays on a null-position, he goes to the nearest non null-position around that null-position + while (mSearchNodes[(int)start.X, (int)start.Y] == null) + { + if (startXPos.X < mLevelWidth) + startXPos.X++; + if (startXNeg.X > 0) + startXNeg.X--; + if (startYPos.Y < mLevelHeight) + startYPos.Y++; + if (startYNeg.Y > 0) + startYNeg.Y--; + + if (mSearchNodes[(int)startXPos.X, (int)start.Y] != null) + { + start.X = startXPos.X; + return start; + } + if (mSearchNodes[(int)startXNeg.X, (int)start.Y] != null) + { + start.X = startXNeg.X; + return start; + } + if (mSearchNodes[(int)start.X, (int)startYPos.Y] != null) + { + start.Y = startYPos.Y; + return start; + } + if (mSearchNodes[(int)start.X, (int)startYNeg.Y] != null) + { + start.Y = startYNeg.Y; + return start; + } + } + return start; + } + + private Vector2 CheckEndNode(Vector2 endNode) + { + var end = endNode; + + var endXPos = endNode; + var endXNeg = endNode; + var endYPos = endNode; + var endYNeg = endNode; + + // When goal is null-position, the goal will be the nearest non null-position around that null-position + while (mSearchNodes[(int) end.X, (int) end.Y] == null) + { + if(endXPos.X < mLevelWidth - 3) + endXPos.X++; + if(endXNeg.X > 0) + endXNeg.X--; + if(endYPos.Y < mLevelHeight - 3) + endYPos.Y++; + if(endYNeg.Y > 0) + endYNeg.Y--; + + if (endXPos.X > mLevelWidth - 3) + break; + if (endXNeg.X < 0) + break; + if (endYPos.Y > mLevelHeight - 3) + break; + if (endYNeg.Y < 0) + break; + + if (mSearchNodes[(int)endXPos.X, (int)end.Y] != null) + { + end.X = endXPos.X; + return end; + } + if (mSearchNodes[(int)endXNeg.X, (int)end.Y] != null) + { + end.X = endXNeg.X; + return end; + } + if (mSearchNodes[(int)end.X, (int)endYPos.Y] != null) + { + end.Y = endYPos.Y; + return end; + } + if (mSearchNodes[(int)end.X, (int)endYNeg.Y] != null) + { + end.Y = endYNeg.Y; + return end; + } + } + return end; + } + + // Finds the best path + public List FindPath(Vector2 startPoint, Vector2 endPoint) + { + // Start to find path if startpoint and endpoint are different + if (startPoint == endPoint) + { + return new List(); + } + + // Sprite don't walk out of the map + if (endPoint.Y > mLevelHeight - 2 || endPoint.Y < 4 || endPoint.X > mLevelWidth - 2 || endPoint.X < 2) + { + return new List(); + } + + // Test nodes for their validity + startPoint = CheckStartNode(startPoint); + endPoint = CheckEndNode(endPoint); + + /* + * Clear the open and closed lists. + * reset each's node F and G values + */ + ResetSearchNodes(); + + // Store references to the start and end nodes for convenience + SearchNode startNode = mSearchNodes[(int)startPoint.X, (int)startPoint.Y]; + SearchNode endNode = mSearchNodes[(int)endPoint.X, (int)endPoint.Y]; + + /* + * Set the start node’s G value to 0 and its F value to the + * estimated distance between the start node and goal node + * (this is where our H function comes in) and add it to the open list + */ + if (startNode != null) + { + startNode.mInOpenList = true; + + startNode.mDistanceToGoal = Heuristic(startPoint, endPoint); + startNode.mDistanceTraveled = 0; + + mOpenList.Add(startNode); + } + + /* + * While the OpenList is not empty: + */ + while (mOpenList.Count > 0) + { + // Loop the open list and find the node with the smallest F value + SearchNode currentNode = FindBestNode(); + + // If the open list ist empty or a node can't be found + if (currentNode == null) + break; + + // If the active node ist the goal node, we will find and return the path + if (currentNode == endNode) + return FindFinalPath(startNode, endNode); // Trace our path back to the start + + // Else, for each of the active node's neighbors + for (int i = 0; i < currentNode.mNeighbors.Length; i++) + { + SearchNode neighbor = currentNode.mNeighbors[i]; + + // Make sure that the neighbor can be walked on + if (neighbor == null || !neighbor.mWalkable) + continue; + + // Calculate a new G Value for the neighbors node + float distanceTraveled = currentNode.mDistanceTraveled + 1; + + // An estimate of t he distance from this node to the end node + float heuristic = Heuristic(neighbor.mPosition, endPoint); + + if (!neighbor.mInOpenList && !neighbor.mInClosedList) + { + // Set the neighbors node G value to the G value + neighbor.mDistanceTraveled = distanceTraveled; + + // Set the neighboring node's F value to the new G value + the estimated + // distance between the neighbouring node and goal node + neighbor.mDistanceToGoal = distanceTraveled + heuristic; + + // The neighbouring node's mParent property to point at the active node + neighbor.mParent = currentNode; + + // Add the neighboring node to the open list + neighbor.mInOpenList = true; + mOpenList.Add(neighbor); + } + + // Else if the neighboring node is in open or closed list + else if (neighbor.mInOpenList || neighbor.mInClosedList) + { + if (neighbor.mDistanceTraveled > distanceTraveled) + { + neighbor.mDistanceTraveled = distanceTraveled; + neighbor.mDistanceToGoal = distanceTraveled + heuristic; + + neighbor.mParent = currentNode; + } + } + } + + // Remove active node from the open list and add to the closed list + mOpenList.Remove(currentNode); + currentNode.mInOpenList = true; + + } + + // No path could be found + return new List(); + } + + // Check whether an area is completely walkable in given rectangle + public bool AllWalkable(Rectangle rectangle) + { + for (int x = rectangle.X; x <= rectangle.X + rectangle.Width; x++) + { + for (int y = rectangle.Y; y <= rectangle.Y + rectangle.Height; y++) + { + if (mSearchNodes[x / 16, y / 16] == null) + return false; + } + } + return true; + } + + //Raycasting + private bool RayCast(Vector2 start, Vector2 goal) + { + var direction = goal - start; + var currentPos = start; + direction.Normalize(); + //direction = direction * 8; + + while (Vector2.Distance(currentPos, goal) > 1f) + { + if (mSearchNodes[(int)currentPos.X / 16, (int)currentPos.Y / 16] == null) + return false; + currentPos += direction; + } + return true; + } + } +} diff --git a/V3/Map/PathfindingGrid.cs b/V3/Map/PathfindingGrid.cs new file mode 100644 index 0000000..266ea02 --- /dev/null +++ b/V3/Map/PathfindingGrid.cs @@ -0,0 +1,125 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; + +namespace V3.Map +{ + /// + /// Tells the pathfinder where you can walk. + /// + public sealed class PathfindingGrid + { + private const int CellHeight = Constants.CellHeight; + private const int CellWidth = Constants.CellWidth; + + private readonly bool[,] mArray; + public readonly int mGridWidth; + public readonly int mGridHeight; + private Texture2D mTexture; + private Texture2D mMinimapTexture; + + public PathfindingGrid(int mapWidth, int mapHeight, int tileWidth, int tileHeight) + { + mGridHeight = (mapHeight - 1) * tileHeight / CellHeight / 2; + mGridWidth = (mapWidth - 1) * tileWidth / CellWidth; + mArray = new bool[mGridHeight, mGridWidth]; + } + + /// + /// Compares the pathfinding grid with the given collision grid and adjusts the former. + /// If a cell of the pathfinding grid is false and the cell at the same position of the + /// collision grid is true, switch false to true. + /// + /// A grid of the same size as the pathfinding grid. + public void CreateCollisions(bool[,] collisionGrid) + { + if (collisionGrid.Length == mGridWidth * mGridHeight) + { + for (int i = 0; i < mGridHeight; i++) + { + for (int j = 0; j < mGridWidth; j++) + { + if (!mArray[i, j]) + { + mArray[i, j] = collisionGrid[i, j]; + } + } + } + } + else + { + throw new Exception("Error creating the collision grid. Object layer data and collision grid data do not fit."); + } + } + + /// + /// Load content for visual representation of the pathfinding grid. + /// + /// Use this content manager. + public void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Textures/pathfinder"); + //mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); + } + + /// + /// A visual representation of the pathfinding grid. Drawn efficiently. + /// + /// Sprite batch used for drawing. + /// For only drawing on the shown part of the map. + public void Draw(SpriteBatch spriteBatch, ICamera camera) + { + Point startPosition = camera.Location.ToPoint() / new Point(CellWidth, CellHeight); + Point tilesOnScreen = camera.ScreenSize / new Point(CellWidth, CellHeight) + new Point(1, 1) + startPosition; + for (int i = startPosition.Y; i < tilesOnScreen.Y && i < mGridHeight; i++) + { + for (int j = startPosition.X; j < tilesOnScreen.X && j < mGridWidth; j++) + { + Rectangle destinationRectangle = new Rectangle(j * CellWidth, i * CellHeight, CellWidth, CellHeight); + Rectangle sourceRectangle = new Rectangle(mArray[i, j] ? CellWidth : 0, 0, CellWidth, CellHeight); + spriteBatch.Draw(mTexture, destinationRectangle, sourceRectangle, Color.White); + } + } + } + + /// + /// Gets the value at the specified position of the collision array. + /// + /// Position at the horizontal axis. + /// Position at the vertical axis. + /// Returns 0 if you can walk at the specified position, 1 otherwise. + public int GetIndex(int cellX, int cellY) + { + //if (cellX < 0 || cellX > mGridWidth - 1 || cellY < 0 || cellY > mGridHeight - 1) + // return 0; + return mArray[cellY, cellX] ? 1 : 0; + } + + /// + /// Draws a small version of the pathfinding grid to the screen. + /// Useful for the minimap. + /// + /// Sprite batch used. + /// Where to draw in pixel coordinates and which size. In pixels. + public void DrawSmallGrid(SpriteBatch spriteBatch, Rectangle position) + { + spriteBatch.Draw(mMinimapTexture, position, Color.White); + } + + public void CreateMinimap(GraphicsDevice device) + { + Color[] colors = new Color[mGridWidth * mGridHeight]; + for (int i = 0; i < mGridHeight; i++) + { + for (int j = 0; j < mGridWidth; j++) + { + colors[i * mGridWidth + j ] = mArray[i, j] ? Color.DarkGray : Color.Green; + } + } + mMinimapTexture = new Texture2D(device, mGridWidth, mGridHeight); + mMinimapTexture.SetData(colors); + } + } +} \ No newline at end of file diff --git a/V3/Map/SearchNode.cs b/V3/Map/SearchNode.cs new file mode 100644 index 0000000..db49f14 --- /dev/null +++ b/V3/Map/SearchNode.cs @@ -0,0 +1,31 @@ +using Microsoft.Xna.Framework; + +namespace V3.Map +{ + class SearchNode + { + // Location on the map + public Vector2 mPosition; + + // If true, the sprite can walk on + public bool mWalkable; + + // + public SearchNode[] mNeighbors; + + // Previous node + public SearchNode mParent; + + // Check whether a node is in the open list + public bool mInOpenList; + + // Check whether a node is in the closed list + public bool mInClosedList; + + // DIstance from the start node to the goal node (F value) + public float mDistanceToGoal; + + // Distance traveled from the spawn point (G value) + public float mDistanceTraveled; + } +} \ No newline at end of file diff --git a/V3/Map/TiledParser.cs b/V3/Map/TiledParser.cs new file mode 100644 index 0000000..8171ecf --- /dev/null +++ b/V3/Map/TiledParser.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Xml; +using Microsoft.Xna.Framework; + +namespace V3.Map +{ + /// + /// Parser for the tmx format of the Tiled Map Editor. + /// Reads XML file and returns corresponding data objects. + /// + public sealed class TiledParser + { + private string mFileName; + // Map Data: + public int MapWidth { get; private set; } + public int MapHeight { get; private set; } + public int TileWidth { get; private set; } + public int TileHeight { get; private set; } + public SortedList TileSets { get; } = new SortedList(); + public List MapLayers { get; } = new List(); + public List Areas { get; } = new List(); + + /// + /// Parse the tmx file and hold data in instance properties. + /// + public void Parse(string fileName) + { + mFileName = fileName; + string directory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); + string fullPath = directory + "/Content/Maps/" + mFileName + ".tmx"; + int p = (int)Environment.OSVersion.Platform; + if ((p == 4) || (p == 6) || (p == 128)) // Running on Unix + fullPath = fullPath.Substring(5); +#if DEBUG + Console.WriteLine("Loading Map: " + fullPath); +#endif + XmlReader reader = XmlReader.Create(fullPath); + while (reader.Read()) + { + if (reader.IsStartElement()) + { + switch (reader.Name) + { + case "map": + ParseMapData(reader); + break; + case "tileset": + ParseTilesetData(reader); + break; + case "layer": + ParseLayerData(reader); + break; + case "objectgroup": + ParseObjectgroup(reader); + break; + } + } + } + } + + private void ParseMapData(XmlReader reader) + { + while (reader.MoveToNextAttribute()) + { + switch (reader.Name) + { + case "width": + MapWidth = reader.ReadContentAsInt(); + break; + case "height": + MapHeight = reader.ReadContentAsInt(); + break; + case "tilewidth": + TileWidth = reader.ReadContentAsInt(); + break; + case "tileheight": + TileHeight = reader.ReadContentAsInt(); + break; + } + } + reader.MoveToElement(); + } + + private void ParseTilesetData(XmlReader reader) + { + if (reader.HasAttributes) + { + List tilesetAttributes = new List(); + // Read attributes firstgid, name, tilewidth, tileheight, tilecount, columns. + for (int i = 0; i < reader.AttributeCount; i++) + { + tilesetAttributes.Add(reader[i]); + } + reader.MoveToElement(); + // Read attributes for tileoffset x and y if existing. + while (reader.Read()) + { + if (reader.Name == "tileoffset") + { + if (reader.IsStartElement()) + { + for (int i = 0; i < reader.AttributeCount; i++) + { + tilesetAttributes.Add(reader[i]); + } + } + else + { + break; + } + } + else if (reader.Name == "tile" || reader.Name == "tileset") + { + break; + } + } + if (tilesetAttributes.Count == 6) + { + TileSets.Add(int.Parse(tilesetAttributes[0]), new Tileset(tilesetAttributes[1], int.Parse(tilesetAttributes[2]), + int.Parse(tilesetAttributes[3]), int.Parse(tilesetAttributes[5]))); + } + else if (tilesetAttributes.Count == 8) + { + TileSets.Add(int.Parse(tilesetAttributes[0]), new Tileset(tilesetAttributes[1], int.Parse(tilesetAttributes[2]), + int.Parse(tilesetAttributes[3]), int.Parse(tilesetAttributes[5]), + int.Parse(tilesetAttributes[6]), int.Parse(tilesetAttributes[7]))); + } + else + { + throw new Exception("Error parsing tileset element in " + mFileName + ".tmx. Does not contain necessary attributes."); + } + ParseCollisionData(reader, int.Parse(tilesetAttributes[0])); + } + } + + private void ParseLayerData(XmlReader reader) + { + while (reader.MoveToNextAttribute()) + { + if (reader.Name == "width") + { + // TODO: Try catching exceptions and throw specific ones. + int width = reader.ReadContentAsInt(); + reader.MoveToNextAttribute(); + int height = reader.ReadContentAsInt(); + reader.MoveToElement(); + reader.ReadToDescendant("data"); + MapLayers.Add(new int[height, width]); + int currentLayerIndex = MapLayers.Count - 1; + // Map data is in CSV format, therefore split at comma. + string[] layerData = reader.ReadString().Split(','); + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + MapLayers[currentLayerIndex][i, j] = int.Parse(layerData[i * width + j]); + } + } + } + } + reader.MoveToElement(); + } + + private void ParseCollisionData(XmlReader reader, int currentTileset) + { + do + { + if (!reader.IsStartElement() && reader.Name == "tileset") + { + // If the end of the tileset note is reached, leave loop. + break; + } + if (reader.IsStartElement() && reader.Name == "tile" && reader.HasAttributes) + { + string tileId = reader[0]; + reader.MoveToElement(); + while (reader.ReadToDescendant("property")) + { + if (reader.MoveToAttribute("name") && reader.Value == "collision") + { + reader.MoveToNextAttribute(); + string collisionData = reader.Value; + Tileset tileset = TileSets[currentTileset]; + if (tileId != null) tileset.AddCollisionData(int.Parse(tileId), collisionData); + } + } + } + } + while (reader.Read()) ; + } + + private void ParseObjectgroup(XmlReader reader) + { + do + { + if (!reader.IsStartElement() && reader.Name == "objectgroup") + break; + if (reader.IsStartElement() && reader.Name == "object") + { + ParseAreaData(reader); + } + } while (reader.Read()); + } + + private void ParseAreaData(XmlReader reader) + { + string type; + string name = ""; + double density = 0; + double chance = 0; + Rectangle rectangle; + if (reader.AttributeCount == 7) + { + name = reader[1]; + type = reader[2]; + if (!(reader[3] != null && reader[4] != null && reader[5] != null && reader[6] != null)) + return; + rectangle = new Rectangle(int.Parse(reader[3]), int.Parse(reader[4]), int.Parse(reader[5]), int.Parse(reader[6])); + } + else if (reader.AttributeCount == 6) + { + type = reader[1]; + if (!(reader[2] != null && reader[3] != null && reader[4] != null && reader[5] != null)) + return; + rectangle = new Rectangle(int.Parse(reader[2]), int.Parse(reader[3]), int.Parse(reader[4]), int.Parse(reader[5])); + } + else + { + throw new Exception("Error parsing the map. One of the objects has not the right number of attributes, specifically: " + reader.AttributeCount); + } + reader.MoveToElement(); + while (reader.Read()) + { + if (!reader.IsStartElement() && reader.Name == "properties") + break; + if (reader.Name == "property" && reader.HasAttributes) + { + if (reader[2] == null) return; + if (reader[0] == "chance") + { + chance = double.Parse(reader[2], CultureInfo.InvariantCulture); + } + else if (reader[0] == "density") + { + density = double.Parse(reader[2], CultureInfo.InvariantCulture); + } + reader.MoveToElement(); + } + } + Area area = new Area(type, rectangle, density, chance, name); + Areas.Add(area); + } + } +} diff --git a/V3/Map/Tileset.cs b/V3/Map/Tileset.cs new file mode 100644 index 0000000..aa12885 --- /dev/null +++ b/V3/Map/Tileset.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; + +namespace V3.Map +{ + /// + /// Class for holding information needed of Tilesets. Needed to draw the map. + /// + public sealed class Tileset + { + private const int CellHeight = Constants.CellHeight; + private const int CellWidth = Constants.CellWidth; + + /// + /// Name of the tileset, often the filename. + /// + public string Name { get; } + /// + /// Tile width of each tile in pixel. + /// + public int TileWidth { get; } + /// + /// Tile height of each tile in pixel. + /// + public int TileHeight { get; } + + /// + /// Columns of tiles of the tileset image. + /// + public int Columns { get; private set; } + /// + /// When tile is drawn, is there an offset needed on the X axis for correct display. + /// + public int OffsetX { get; private set; } + /// + /// + /// When tile is drawn, is there an offset needed on the Y axis for correct display. + /// + public int OffsetY { get; private set; } + /// + /// Each tile of the tileset, represented by an integer, can hold collision data consisting of a two dimensional + /// array of boolean values. Its size is described by CollisionWidth and CollisionHeight. + /// + public Dictionary TileCollisions { get; } + public int CollisionWidth => TileWidth / CellWidth; + public int CollisionHeight => TileHeight / CellHeight; + + public Tileset(string name, int tileWidth, int tileHeight, int columns, int offsetX = 0, int offsetY = 0) + { + Name = name; + TileWidth = tileWidth; + TileHeight = tileHeight; + Columns = columns; + OffsetX = offsetX; + OffsetY = offsetY; + // TODO: Fill dictionary with TiledParser. + TileCollisions = new Dictionary(); + } + + /// + /// Add an entry to the collision dictionary for the specific tile. + /// + /// The tile ID in the tileset. + /// The corresponding collision data as string of '0' and '1'. + public void AddCollisionData(int tileId, string collisionData) + { + int gridWidth = CollisionWidth; + int gridHeight = CollisionHeight; + bool[,] dataArray = new bool[gridHeight, gridWidth]; + for (int i = 0; i < gridHeight; i++) + { + for (int j = 0; j < gridWidth; j++) + { + try + { + dataArray[i, j] = collisionData[i * gridWidth + j] == '1'; + } + catch (IndexOutOfRangeException e) + { + throw new IndexOutOfRangeException("Inconsistencies with the collision data of Tile " + + tileId + " in tileset " + Name + ". Check corresponding tmx file or" + + "contact the programmer: Thomas.", e); + } + } + } + TileCollisions.Add(tileId, dataArray); + } + } +} \ No newline at end of file diff --git a/V3/Node.cs b/V3/Node.cs new file mode 100644 index 0000000..7c01820 --- /dev/null +++ b/V3/Node.cs @@ -0,0 +1,467 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using V3.Objects; +using Rectangle = Microsoft.Xna.Framework.Rectangle; + +namespace V3 +{ + public sealed class Node + { + /// + /// Represents the Rectangle if a Quad gets split + /// + private Node mRt; // The rectangle on the right top + private Node mLt; // The rectangle on the left top + private Node mRb; // The rectangle on the right bottom + private Node mLb; // The rectangle on the left bottom + private readonly Node mParent; // the parent of a node + private Rectangle mRectangle; + private readonly int mPositionX; // X position of the current rectangle + private readonly int mPositionY; // Y position of the current rectangle + private readonly int mSizeX; // length of the current rectangle + private readonly int mSizeY; // width of the current rectangle + private readonly int mCenterX; // center of the current rectangle + private readonly int mCenterY; + private int mCount; + private Rectangle mCreatureRectangle; + private MovementDirection mMovementDirectionItem2; + private MovementState mMovementStateItem; + private MovementState mMovementStateItem2; + + /// + /// The list of each node where the objects in each rectangle are saved + /// + private List mObjectList = new List(); + private int Count => ObjectCount(); + + /// + /// initialize the Node + /// + /// the current Rectangle/size of the Node + /// the parent of the node + public Node(Rectangle currentRectangle, Node p) + { + mParent = p; + mRectangle = currentRectangle; + mPositionY = mRectangle.Y; + mPositionX = mRectangle.X; + mSizeX = mRectangle.Width; + mSizeY = mRectangle.Height; + mCenterY = mRectangle.Y + mRectangle.Height / 2; + mCenterX = mRectangle.X + mRectangle.Width / 2; + } + + /// + /// divided the rectangle in 4 small rectangles locaded in it self + /// + private void CreateSubnodes() + { + if (mLt == null) + { + mLt = new Node(new Rectangle(mPositionX - 1, mPositionY - 1, mSizeX / 2 + 2, mSizeY / 2 + 2), + this); + mRt = new Node(new Rectangle(mPositionX + mSizeX / 2, mPositionY - 1, mSizeX / 2 + 1, mSizeY / 2 + 2), + this); + mLb = new Node(new Rectangle(mPositionX - 1, mPositionY + mSizeY / 2, mSizeX / 2 + 2, mSizeY / 2 + 1), + this); + mRb = new Node( new Rectangle(mPositionX + mSizeX / 2, mPositionY + mSizeY / 2, mSizeX / 2 + 1, mSizeY / 2 + 1), + this); + } + } + + /// + /// This method is looking in which rectangle the object is located. + /// At first it checks in which part (right top, left top...) of the rectangle the object is + /// and if its posibible the rectangle gets split in for new rectangles the same is happening again. + /// + /// Type of Creature including their position. + public void AddtoSubNode(IGameObject item) + { + mCreatureRectangle = item.BoundaryRectangle; + + if (mRectangle.Contains(mCreatureRectangle)) + { + if (mCreatureRectangle.Right < mCenterX && (mCreatureRectangle.Y + mCreatureRectangle.Height) < mCenterY) + { + CreateSubnodes(); // splits subnode in more subnodes + mLt.AddtoSubNode(item); + } + else if (mCreatureRectangle.X > mCenterX && (mCreatureRectangle.Y + mCreatureRectangle.Height) < mCenterY) + { + CreateSubnodes(); + mRt.AddtoSubNode(item); + } + else if (mCreatureRectangle.Right < mCenterX && mCreatureRectangle.Y > mCenterY) + { + CreateSubnodes(); + mLb.AddtoSubNode(item); + } + else if (mCreatureRectangle.X > mCenterX && mCreatureRectangle.Y > mCenterY) + { + CreateSubnodes(); + mRb.AddtoSubNode(item); + } + else + { + mObjectList.Add(item); // the object gets added to the objectlist of the current node/subnode + //CheckCollission(mObjectList); + mCount++; + if (mCount == 8) + { + CheckCollission(mObjectList); + } + else if (mCount > 8) + { + mCount = 0; + } + } + } + } + + /// + /// checks if the Objects in the same Quad are intersecting + /// + /// list with the objects in the same quad + //void CheckCollission(List objectList) + void CheckCollission(List objectList) + { + // if (mParent != null) + // { + // mList2 = mParent.mObjectList; + // } + + foreach (var obj in objectList) + { + foreach (var obj2 in objectList) + { + if (Equals(obj, obj2)) + { + continue; + } + if (obj.BoundaryRectangle.Intersects(obj2.BoundaryRectangle)) + //if (obj.BoundaryRectangle.X < obj2.BoundaryRectangle.X + obj2.BoundaryRectangle.Width && + //obj.BoundaryRectangle.X + obj.BoundaryRectangle.Width > obj2.BoundaryRectangle.X && + //obj.BoundaryRectangle.Y < obj2.BoundaryRectangle.Y + obj2.BoundaryRectangle.Height && + //obj.BoundaryRectangle.Height + obj.BoundaryRectangle.Y > obj2.BoundaryRectangle.Y) + { + + if (!(obj is ICreature)) return; + if (!(obj2 is ICreature)) return; + ICreature creature = (ICreature)obj; + mMovementStateItem = creature.MovementState; + ICreature creature2 = (ICreature)obj2; + mMovementStateItem2 = creature2.MovementState; + if (mMovementStateItem != MovementState.Dying && (mMovementStateItem2 != MovementState.Dying)) + { + HandleCollision(obj, obj2); + } + } + } + } + + //if (mParent != null) + //{ + // foreach (var obj in mList2) + // { + // foreach (var obj2 in objectList) + // { + // if (obj == obj2) + // { + // continue; + // } + // if (obj.BoundaryRectangle.Intersects(obj2.BoundaryRectangle)) + // //if (obj.BoundaryRectangle.X < obj2.BoundaryRectangle.X + obj2.BoundaryRectangle.Width && + // // obj.BoundaryRectangle.X + obj.BoundaryRectangle.Width > obj2.BoundaryRectangle.X && + // // obj.BoundaryRectangle.Y < obj2.BoundaryRectangle.Y + obj2.BoundaryRectangle.Height && + // // obj.BoundaryRectangle.Height + obj.BoundaryRectangle.Y > obj2.BoundaryRectangle.Y) + // { + // if (!(obj is ICreature)) return; + // if (!(obj2 is ICreature)) return; + // //if (obj.GetType() != typeof(ICreature)) return; + // ICreature creature = (ICreature)obj; + // mMovementStateItem = creature.MovementState; + // ICreature creature2 = (ICreature)obj2; + // mMovementStateItem2 = creature2.MovementState; + // if (mMovementStateItem != MovementState.Dying && (mMovementStateItem2 != MovementState.Dying)) + // { + // HandleCollision(obj, obj2); + // } + // //mCollision = true; + // } + // } + // } + //} + } + + /// + /// If collsion is detected the object gets moved away so there is no collision anymore + /// + /// the object which collid with another object + /// the other object + //void HandleCollision(AbstractCreature item, AbstractCreature item2) + void HandleCollision(IGameObject item, IGameObject item2) + { + ICreature creature = (ICreature)item; + ICreature creature2 = (ICreature)item2; + mMovementDirectionItem2 = creature2.MovementDirection; + + if (mMovementDirectionItem2 == MovementDirection.S) + { + creature.Position = new Vector2(item.Position.X + 1, item.Position.Y); + } + if (mMovementDirectionItem2 == MovementDirection.N) + { + creature.Position = new Vector2(item.Position.X + 1, item.Position.Y); + } + else if (mMovementDirectionItem2 == MovementDirection.O) + { + creature.Position = new Vector2(item.Position.X, item.Position.Y + 1); + } + else if (mMovementDirectionItem2 == MovementDirection.W) + { + creature.Position = new Vector2(item.Position.X, item.Position.Y + 1); + } + else if (mMovementDirectionItem2 == MovementDirection.SO) + { + creature.Position = new Vector2(item.Position.X - 1, item.Position.Y); + } + else if (mMovementDirectionItem2 == MovementDirection.NO) + { + creature.Position = new Vector2(item.Position.X + 1, item.Position.Y - 1); + } + else if (mMovementDirectionItem2 == MovementDirection.NW) + { + creature.Position = new Vector2(item.Position.X - 1, item.Position.Y + 1); + } + else if (mMovementDirectionItem2 == MovementDirection.SW) + { + creature.Position = new Vector2(item.Position.X + 1, item.Position.Y); + } + else + { + creature.Position = new Vector2(item.Position.X + 1, item.Position.Y + 1); + } + } + + /// + /// Clears the QuadTree of all objects, including any objects living in its children. + /// + public void Clear() + { + // Clear out the children, if we have any + if (mLt != null) + { + mLt.Clear(); + mRt.Clear(); + mLb.Clear(); + mRb.Clear(); + } + + // Clear any objects at this level + if (mObjectList != null) + { + mObjectList.Clear(); + mObjectList = null; + } + + // Set the children to null + mLt = null; + mRt = null; + mLb = null; + mRb = null; + } + + /// + /// Get the total for all objects in this QuadTree, including children. + /// + /// The number of objects contained within this QuadTree and its children. + private int ObjectCount() + { + int count = 0; + + // Add the objects at this level + if (mObjectList != null) count += mObjectList.Count; + + // Add the objects that are contained in the children + if (mLt != null) + { + count += mLt.ObjectCount(); + count += mRt.ObjectCount(); + count += mLb.ObjectCount(); + count += mRb.ObjectCount(); + } + + return count; + } + + + /// + /// Deletes an item from this QuadTree. If the object is removed causes this Quad to have no objects in its children, + /// it's children will be removed as well. + /// + /// + public void Delete(IGameObject item) + { + if (mObjectList.Contains(item)) + { + mObjectList.Remove(item); + } + // If we didn't find the object in this tree, try to delete from its children + else if (mLt != null) + { + mLt.Delete(item); + mRt.Delete(item); + mLb.Delete(item); + mRb.Delete(item); + } + + // If all the children are empty, delete all the children + if (mLt?.Count == 0 && + mRt.Count == 0 && + mLb.Count == 0 && + mRb.Count == 0) + { + mLt = null; + mRt = null; + mLb = null; + mRb = null; + } + } + + /// + /// If the Object isnt in his old Rectangle anymore it have to move + /// the object to the parent(s) Rectangle until it fits, and optionally going back down into children + /// + /// Actuell Creature + private void Move(IGameObject item) + { + if (mParent != null && mParent.mRectangle.Contains(item.BoundaryRectangle)) + { + mParent.AddtoSubNode(item); + } + else if (mParent == null) + { + AddtoSubNode(item); + } + else + { + mParent.Move(item); + } + + } + + /// + /// If four Subnodes are empty the get deleted + /// + private void RemoveEmptyNodes() + { + // If all the children are empty, delete all the children + if (mLt?.Count == 0 && + mRt.Count == 0 && + mLb.Count == 0 && + mRb.Count == 0) + { + mLt = null; + mRt = null; + mLb = null; + mRb = null; + } + mLt?.RemoveEmptyNodes(); + mRt?.RemoveEmptyNodes(); + mLb?.RemoveEmptyNodes(); + mRb?.RemoveEmptyNodes(); + } + + + /// + /// Gibt einem alle Argumente die Innerhalb des rectangles sind zurück in der Liste objectInRecList + /// + /// Der Bereich aus dem man alle Objecte haben möchte + /// Die Liste, in der alle Objekte enthalten sind, die sich im gefragten Rectangle aufhalten + /// + public List GetObjectsInRectangle(Rectangle rectangle, List objectInRecList) + { + if (rectangle.Intersects(mRectangle)) + { + if (mObjectList != null) + { + foreach (var obj in mObjectList) + { + if (obj.GetSelf() != null) + { + objectInRecList.Add(obj); + } + } + } + if (mLt != null) + { + mLt.GetObjectsInRectangle(rectangle, objectInRecList); + mRt.GetObjectsInRectangle(rectangle, objectInRecList); + mLb.GetObjectsInRectangle(rectangle, objectInRecList); + mRb.GetObjectsInRectangle(rectangle, objectInRecList); + } + } + return objectInRecList; + } + + + /// + /// Updates the position of the object in the Quadtree. If they changed their position + /// they get deleted and added again at the correct position. + /// + public void Update1() + { + List copyList = new List(mObjectList); + //CheckCollission(mObjectList); + foreach (IGameObject obj in copyList) + { + if (!(obj is ICreature)) + continue; + Delete(obj); + if (mRectangle.Contains(obj.BoundaryRectangle)) + { + AddtoSubNode(obj); + } + // if Creature isnt there anymore -> move + else + { + Move(obj); + break; + } + } + mLt?.Update1(); + mRt?.Update1(); + mRb?.Update1(); + mLb?.Update1(); + RemoveEmptyNodes(); + } + + /// + /// Makes the Quadtree visible + /// + /// to draw the Rectangles + /// + public void DrawQuadtree(SpriteBatch spriteBatch, Texture2D texture) + { + //spriteBatch.Draw(mQuadtree.Texture, mRectangle, Color.Black); + spriteBatch.Draw(texture, new Rectangle(mPositionX, mPositionY, mSizeX, 2), Color.Black); + spriteBatch.Draw(texture, new Rectangle(mPositionX, mPositionY, 2, mSizeY), Color.Black); + spriteBatch.Draw(texture, new Rectangle(mPositionX + mSizeX, mPositionY, 2, mSizeY), Color.Black); + spriteBatch.Draw(texture, new Rectangle(mPositionX, mPositionY + mSizeY, mSizeX, 2), Color.Black); + mLt?.DrawQuadtree(spriteBatch, texture); + mRt?.DrawQuadtree(spriteBatch, texture); + mLb?.DrawQuadtree(spriteBatch, texture); + mRb?.DrawQuadtree(spriteBatch, texture); + + // Draws the rectangle of each Creature + //foreach (var obj in mObjectList) + //{ + // spriteBatch.Draw(mQuadtree.Texture, new Rectangle(obj.BoundaryRectangle.X, obj.BoundaryRectangle.Y, obj.BoundaryRectangle.Width, 5), Color.Red); + // spriteBatch.Draw(mQuadtree.Texture, new Rectangle(obj.BoundaryRectangle.X, obj.BoundaryRectangle.Y, 5, obj.BoundaryRectangle.Height), Color.Red); + // spriteBatch.Draw(mQuadtree.Texture, new Rectangle(obj.BoundaryRectangle.X + obj.BoundaryRectangle.Width, obj.BoundaryRectangle.Y, 5, obj.BoundaryRectangle.Height), Color.Red); + // spriteBatch.Draw(mQuadtree.Texture, new Rectangle(obj.BoundaryRectangle.X, obj.BoundaryRectangle.Y + obj.BoundaryRectangle.Height, obj.BoundaryRectangle.Width, 5), Color.Red); + //} + } + } +} diff --git a/V3/Objects/AbstractBuilding.cs b/V3/Objects/AbstractBuilding.cs new file mode 100644 index 0000000..bc6061c --- /dev/null +++ b/V3/Objects/AbstractBuilding.cs @@ -0,0 +1,110 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects +{ + public abstract class AbstractBuilding : IBuilding + { + private readonly string mTextureName; + private Texture2D mTexture; + private readonly BuildingFace mFacing; + private Rectangle mTilesetRectangle; + + public Vector2 Position { get; set; } + protected abstract int MaxRobustness { get; } + public abstract int Robustness { get; protected set; } + public abstract string Name { get; } + public virtual int MaxGivesWeapons { get; protected set; } + private bool mIsDestroyed; + public Rectangle BoundaryRectangle { get; } + public int Id { get; } + + protected AbstractBuilding(Vector2 position, Rectangle size, string textureName, BuildingFace facing) + { + Position = position; + Id = IdGenerator.GetNextId(); + // TODO: Hella ugly code + mTilesetRectangle = size; + // Boundary rectangle is smaller than the texture size: + if (this is Castle) + { + BoundaryRectangle = new Rectangle(size.X + 96, size.Y + 296, 900, 500); + } + else + { + BoundaryRectangle = new Rectangle(size.X, size.Y + size.Height / 2, size.Width * 4 / 5, size.Height / 2); + } + mTextureName = textureName; + mFacing = facing; + } + + public void Draw(SpriteBatch spriteBatch) + { + int status = 0; + if (mIsDestroyed) + { + status = 2; + } + else if (Robustness < MaxRobustness / 2) + { + status = 1; + } + Rectangle source = new Rectangle(status * mTilesetRectangle.Width, (mFacing == BuildingFace.SW ? 0 : 1) * mTilesetRectangle.Height + (this is Forge ? 384 : 0), mTilesetRectangle.Width, mTilesetRectangle.Height); + spriteBatch.Draw(mTexture, mTilesetRectangle, source, Color.White); + } + + + public void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Textures/" + mTextureName); + //mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); + } + + public void TakeDamage(int damage) + { + if (Robustness > 0) + { + Robustness -= damage; + } + + if (Robustness <= 0) + { + Destroyed(); + } + } + + public void UpgradeCounter() + { + MaxGivesWeapons -= 1; + } + + + private void Destroyed() + { + mIsDestroyed = true; + } + + public IGameObject GetSelf() + { + return this; + } + + public override bool Equals(Object obj) + { + if (obj == null) + return false; + if (obj == this) + return true; + if (!(obj is IGameObject)) + return false; + return Id.Equals(((IGameObject) obj).Id); + } + + public override int GetHashCode() + { + return Id; + } + } +} diff --git a/V3/Objects/AbstractCreature.cs b/V3/Objects/AbstractCreature.cs new file mode 100644 index 0000000..a4ac419 --- /dev/null +++ b/V3/Objects/AbstractCreature.cs @@ -0,0 +1,911 @@ +using System; +using System.Collections.Generic; +using Castle.Core.Internal; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// Abstract class for deriving all moving objects in the game, + /// be it the player, his minions or the enemy. + /// + public abstract class AbstractCreature : ICreature + { + // ************************************************** + // Internal variables, managers and values. + protected virtual Point CreatureSize { get; } = new Point(24); + protected virtual Point BoundaryShift { get; } = new Point(-12, -16); + protected virtual Point SelectionSize { get; } = new Point(48, 64); + protected virtual Point SelectionShift { get; } = new Point(-24, -40); + /// + /// Array of sprites for drawing the creature. Can have up to four entries for (ordered): Body, Head, Weapon, Offhand + /// + protected abstract ISpriteCreature[] Sprite { get; } + protected abstract IMovable MovementScheme { get; } + protected abstract CreatureType Type { get; } + private Texture2D mOnePixelTexture; + private Texture2D mSelectionTexture; + private readonly Pathfinder mPathfinder; + private readonly ContentManager mContentManager; + private readonly IOptionsManager mOptionsManager; + private AchievementsAndStatistics mAchievementsAndStatistics; + private static readonly Random sRandom = new Random(); + private static readonly object sYncLock = new object(); + private List mArrowList = new List(); + +#if NO_AUDIO +#else + private SoundEffect mSoundEffect; + private SoundEffectInstance mSoundEffectInstance; + private SoundEffect mSoundEffectHorse; + private SoundEffectInstance mSoundEffectInstanceHorse; + private SoundEffect mSoundEffectKnight; + private SoundEffectInstance mSoundEffectInstanceKnight; + private SoundEffect mSoundEffectFight; + private SoundEffectInstance mSoundEffectInstanceFight; + private SoundEffect mSoundEffectMeatball; + private SoundEffectInstance mSoundEffectInstanceMeatball; +#endif + private bool mIsDead; + //private float mReculate = 1.0f; + + // ************************************************** + // Public variables and important attributes of the creature: + public abstract string Name { get; protected set; } + public abstract int Life { get; protected set; } + public abstract int MaxLife { get; protected set; } + public abstract int Speed { get; } + public abstract int Attack { get; protected set; } + public abstract int AttackRadius { get; protected set; } + public abstract int SightRadius { get; protected set; } + public abstract TimeSpan TotalRecovery { get;} + public abstract TimeSpan Recovery { get; set; } + public Vector2 Position { get; set; } + public Vector2 InitialPosition { private get; set; } + public abstract Faction Faction { get; } + public int Id { get; } + + public bool IsDead + { + get { return Life <= 0; } + } + + public bool IsUpgraded { get; set; } + + public abstract IBuilding IsAttackingBuilding { get; set; } + public MovementDirection MovementDirection { get; set; } + public MovementState MovementState { get; set; } = MovementState.Idle; + public Rectangle SelectionRectangle => new Rectangle(Position.ToPoint() + SelectionShift, SelectionSize); + public Rectangle BoundaryRectangle => new Rectangle(Position.ToPoint() + BoundaryShift, CreatureSize); + public bool IsSelected { get; set; } + private static int sMaxNumberOfSoundHorse; + private static int sMaxNumberOfSoundMeatball; + private static int sMaxNumberOfSoundZombie; + private static int sMaxNumberOfSoundKnight; + + public abstract ICreature IsAttacking { get; set; } + + /// + /// Color of the rectangle displayed when creature is selected. + /// + protected virtual Color SelectionColor + { + get + { + switch (Faction) + { + case Faction.Undead: + return Color.Red; + case Faction.Kingdom: + return Color.Blue; + case Faction.Plebs: + return Color.Green; + default: + return Color.Gray; + } + } + } + + protected AbstractCreature(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + { + mPathfinder = pathfinder; + mContentManager = contentManager; + mOptionsManager = optionsManager; + mAchievementsAndStatistics = achievementsAndStatistics; + Id = IdGenerator.GetNextId(); + LoadContent(mContentManager); + } + + /// + /// The specific creature takes damage. If its life falls below zero it dies. + /// + /// Amount of received damage. + public void TakeDamage(int damage) + { + if (Life > 0) + { + Life -= damage; + } + + if (Life <= 0) + { + Die(); + } + } + + /// + /// Loads content files needed for drawing the creature. + /// + /// Content manager used. + public void LoadContent(ContentManager contentManager) + { + Sprite.ForEach(e => e?.Load(contentManager)); + mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); + mSelectionTexture = contentManager.Load("Sprites/selection"); +#if NO_AUDIO +#else + try + { + mSoundEffect = contentManager.Load("Sounds/walking"); + mSoundEffectInstance = mSoundEffect.CreateInstance(); + mSoundEffectHorse = contentManager.Load("Sounds/SkeletonHorse"); + mSoundEffectInstanceHorse = mSoundEffectHorse.CreateInstance(); + mSoundEffectKnight = contentManager.Load("Sounds/Knight"); + mSoundEffectInstanceKnight = mSoundEffectKnight.CreateInstance(); + mSoundEffectFight = contentManager.Load("Sounds/punch"); + mSoundEffectInstanceFight = mSoundEffectFight.CreateInstance(); + mSoundEffectMeatball = contentManager.Load("Sounds/Monster_Gigante-Doberman-1334685792"); + mSoundEffectInstanceMeatball = mSoundEffectMeatball.CreateInstance(); + } + catch (DllNotFoundException) + { + // HACK: ignore sound-related errors as the sound is currently + // not working on the pool computers + } + catch (NoAudioHardwareException) + { + // HACK: ignore sound-related errors as the sound is currently + // not working on the pool computers + } +#endif + } + + /// + /// The creature should move to the specified destination if possible. + /// + /// The desired destination. + public void Move(Vector2 destination) + { + MovementScheme.FindPath(mPathfinder, Position, destination); + } + + public void Update(GameTime gameTime, ICreature playerCharacter, + bool rightButtonPressed, Vector2 rightButtonPosition, Quadtree quadtree, ICamera camera) + { + // If Creature is dead, don't update anymore. + Sprite.ForEach(e => e?.PlayAnimation(gameTime)); + if (mIsDead) + { + return; + } + bool showedByCamera = camera.ScreenRectangle.Contains(Position); +#if NO_AUDIO +#else + + // update the volume according to the current setting + if (mSoundEffectInstance != null) + mSoundEffectInstance.Volume = mOptionsManager.Options.GetEffectiveVolume()*0.1f; + if (mSoundEffectInstanceHorse != null) + mSoundEffectInstanceHorse.Volume = mOptionsManager.Options.GetEffectiveVolume() * 0.07f; + if (mSoundEffectInstanceKnight != null) + mSoundEffectInstanceKnight.Volume = mOptionsManager.Options.GetEffectiveVolume() * 0.07f; + if (mSoundEffectInstanceFight != null) + mSoundEffectInstanceFight.Volume = mOptionsManager.Options.GetEffectiveVolume() * 0.07f; + if (mSoundEffectInstanceMeatball != null) + mSoundEffectInstanceMeatball.Volume = mOptionsManager.Options.GetEffectiveVolume() * 0.07f; +#endif + if (MovementScheme.IsMoving) + { + MovementState = MovementState.Moving; + Position += MovementScheme.GiveNewPosition(Position, Speed); + MovementDirection = MovementScheme.GiveMovementDirection(); +#if NO_AUDIO +#else + try + { + if (showedByCamera) + { + if ((this is Zombie || this is FemalePeasant || this is MalePeasant || this is Necromancer) && + sMaxNumberOfSoundZombie < 3) + { + if (mSoundEffectInstance != null) + { + mSoundEffectInstance.Play(); + sMaxNumberOfSoundZombie++; + } + + } + if (this is SkeletonHorse && sMaxNumberOfSoundHorse < 3) + { + if (mSoundEffectInstanceHorse != null) + { + mSoundEffectInstanceHorse.Play(); + sMaxNumberOfSoundHorse++; + } + + } + if (this is Knight && sMaxNumberOfSoundKnight < 3) + { + if (mSoundEffectInstanceKnight != null) + { + mSoundEffectInstanceKnight.Play(); + sMaxNumberOfSoundKnight++; + } + + } + if (this is Meatball && sMaxNumberOfSoundMeatball < 3) + { + if (mSoundEffectInstanceMeatball != null) + { + mSoundEffectInstanceMeatball.Play(); + sMaxNumberOfSoundMeatball++; + } + + } + } + } + catch (InstancePlayLimitException) + { + // HACK: ignore sound-related errors as the sound is currently + // not working on the pool computers + } +#endif + } + else + { +#if NO_AUDIO +#else + if (mSoundEffectInstance != null) + { + mSoundEffectInstance.Stop(); + sMaxNumberOfSoundZombie--; + } + if (mSoundEffectInstanceHorse != null) + { + mSoundEffectInstanceHorse.Stop(); + sMaxNumberOfSoundHorse--; + } + if (mSoundEffectInstanceKnight != null) + { + mSoundEffectInstanceKnight.Stop(); + sMaxNumberOfSoundKnight--; + } + + if (mSoundEffectInstanceMeatball != null) + { + mSoundEffectInstanceMeatball.Stop(); + sMaxNumberOfSoundMeatball--; + } +#endif + MovementState = MovementState.Idle; + } + if (IsDead) + { + if (mSoundEffectInstance != null) + { + mSoundEffectInstance.Stop(); + sMaxNumberOfSoundZombie--; + } + if (mSoundEffectInstanceHorse != null) + { + mSoundEffectInstanceHorse.Stop(); + sMaxNumberOfSoundHorse--; + } + if (mSoundEffectInstanceKnight != null) + { + mSoundEffectInstanceKnight.Stop(); + sMaxNumberOfSoundKnight--; + } + + if (mSoundEffectInstanceMeatball != null) + { + mSoundEffectInstanceMeatball.Stop(); + sMaxNumberOfSoundMeatball--; + } + } + + /* + * + * Random movement of Zombies + * + */ + #region Random Movement + Ellipse necroArea = new Ellipse(new Vector2((int)playerCharacter.Position.X, (int)playerCharacter.Position.Y), 1280, 640); + float necroDistance = Vector2.Distance(Position, playerCharacter.Position); + List randomMoveVector = new List(); + + + int rndX = RandomNumber(0, 20); + int rndY = RandomNumber(0, 20); + + randomMoveVector.Add(new Vector2(rndX, rndY)); + randomMoveVector.Add(new Vector2(-rndX, -rndY)); + randomMoveVector.Add(new Vector2(rndX, -rndY)); + randomMoveVector.Add(new Vector2(-rndX, rndY)); + + int rndNumber; + + if (!(this is Necromancer) && + Faction.Equals(Faction.Undead) && + MovementState == MovementState.Idle && + !necroArea.Contains(Position)) + { + rndNumber = RandomNumber(1, 60); + if (rndNumber == 7) + { + int rndMoveVector = RandomNumber(0, 400); + Move(Position + randomMoveVector[rndMoveVector%4]); + } + } + if (Faction.Equals(Faction.Plebs)) + { + rndNumber = RandomNumber(1, 60); + if (rndNumber == 7) + { + int rndMoveVector = RandomNumber(0, 400); + Move(Position + randomMoveVector[rndMoveVector%4]); + } + + } + #endregion + + List defenders = new List(); + if (IsAttacking == null) + { + // Get the quadtree of the sight radius. + defenders = quadtree.GetObjectsInRectangle(new Rectangle((int) Position.X - SightRadius/2, (int) Position.Y - SightRadius/2, SightRadius, SightRadius)); + // Returns if nothing is in sight. + if (defenders.Count == 0) return; + } + + bool attacking = false; + + /* + * + * COMMAND ATTACKING OF BUILDINGS + * + */ + #region Command Attack + + // Distance between Undead and Necromancer + if (Faction.Equals(Faction.Undead) && !(this is Necromancer)) + { + // If Undead are in sight distance of the Necromancer, do stuff. + if (IsSelected && (int)necroDistance <= playerCharacter.AttackRadius) + { + // Get all the objects of the quadtree of the sightradius of the Necromancer + if (rightButtonPressed) + { + IsAttackingBuilding = null; + var objectsUnderMouse = quadtree.GetObjectsInRectangle(new Rectangle(rightButtonPosition.ToPoint(), new Point(1, 1))); + foreach (var obj in objectsUnderMouse) + { + var building = obj as IBuilding; + if (building == null || !building.BoundaryRectangle.Contains(rightButtonPosition) || building.Robustness == 0) continue; + IsAttackingBuilding = building; + } + } + } + if (IsAttackingBuilding != null ) + { + if ((int)Vector2.Distance(Position, ComputeMoVector(IsAttackingBuilding)) <= AttackRadius && IsAttackingBuilding.Robustness >= 0) // (int)Vector2.Distance(Position, IsAttackingBuilding.Position) <= AttackRadius * 2 + { + //var building = IsAttacking as IBuilding; + // Attacking + Recovery -= gameTime.ElapsedGameTime; + if (Recovery < TimeSpan.Zero) + { + Recovery = TimeSpan.Zero; + } + MovementState = MovementState.Attacking; // PlayAnimationOnce(MovementState.Attacking, TotalRecovery); + if (Recovery <= TimeSpan.Zero) + { + IsAttackingBuilding.TakeDamage(Attack); + Recovery = TotalRecovery; // Cooldown + + // Throw an arrow + if (AttackRadius > 300) + CreateArrow(Position, IsAttackingBuilding.Position); + } + // If house is dead. + if (IsAttackingBuilding.Robustness <= 20) + { + MovementState = MovementState.Idle; + + // Undead getting stronger if building is dead. + switch (IsAttackingBuilding.Name) + { + case "Schmiede": + if (IsAttackingBuilding.MaxGivesWeapons > 0 && !IsUpgraded) + { + MaxLife += 20; + Life += 20; + IsUpgraded = true; + IsAttackingBuilding.UpgradeCounter(); + } + break; + case "Holzhaus": + if (IsAttackingBuilding.MaxGivesWeapons > 0) + { + if (this is Skeleton && !IsUpgraded) + { + ChangeEquipment(EquipmentType.Body, new SkeletonArcherSprite()); + AttackRadius += 500; + SightRadius += 500; + IsUpgraded = true; + IsAttackingBuilding.UpgradeCounter(); + } + if (this is Zombie && !IsUpgraded) + { + ChangeEquipment(EquipmentType.Body, new ZombieWithClubSprite()); + Attack += 10; + IsUpgraded = true; + IsAttackingBuilding.UpgradeCounter(); + } + } + break; + } + + if (IsAttackingBuilding.Robustness <= 0) IsAttackingBuilding = null; + } + } + else + { + Move(ComputeMoVector(IsAttackingBuilding)); + } + } + } + + #endregion + foreach (var arrow in mArrowList) + { + arrow.UpdateArrow(); + } + /* + * + * AUTO ATTACKING OF CREATURES + * + */ + #region Auto-Attack + + // Don't auto attack if Zombie got command from Necromancer. + if (IsAttackingBuilding != null) return; + + if (IsAttacking == null) + { + List creatures = new List(); + foreach (var defender in defenders) + { + var creature = defender as ICreature; + if (creature == null) continue; + creatures.Add(creature); + } + + ICreature attackableCreature = null; + float sightDistance = SightRadius; + + // Compute the nearest enemy. + foreach (var defender in creatures) + { + // Zombies and Knights only. + if (Faction.Equals(Faction.Undead) || Faction.Equals(Faction.Kingdom)) + { + // If attacker-type == defender-type go to next possible defender. + if ((Faction.Equals(Faction.Undead) && !defender.Faction.Equals(Faction.Undead)) || + (Faction.Equals(Faction.Kingdom) && defender.Faction.Equals(Faction.Undead))) + { + if (defender.Life > 0) + { + // Compute the distance of attacker and possible defender. + float distanceTest = Vector2.Distance(Position, defender.Position); + + if (distanceTest <= sightDistance) + { + sightDistance = distanceTest; + attackableCreature = defender; + } + // IsAttacking = defender; + if (attackableCreature != null) + { + IsAttacking = defender; + + } + } + } + } + } + if (attackableCreature == null) + { + IsAttacking = null; + } + } + + if (IsAttacking == null) return; + /* + * + * ATTACKING OF CREATURES + * + */ + if ((int)Vector2.Distance(Position, IsAttacking.Position) > AttackRadius && + !MovementScheme.IsMoving) + { + // Do not move if attacker is already in attackrange + if (!attacking) + { + Move(ComputeMoVector(IsAttacking)); + } + } + + if (IsAttacking.IsDead || (int)Vector2.Distance(Position, IsAttacking.Position) > SightRadius) + { + IsAttacking = null; + MovementState = MovementState.Idle; + return; + } + // Attacking + Recovery -= gameTime.ElapsedGameTime; + if (Recovery < TimeSpan.Zero) + { + Recovery = TimeSpan.Zero; + } + + // If attacker is in the attack radius of defender + if ((int)Vector2.Distance(Position, IsAttacking.Position) <= AttackRadius) + { + if (Recovery <= TimeSpan.Zero) + { + IsAttacking.TakeDamage(Attack); + PlayAnimationOnce(MovementState.Attacking, TotalRecovery); + Recovery = TotalRecovery; // Cooldown + + // Throw an arrow + if (AttackRadius > 300 && IsAttacking != null) + CreateArrow(Position, IsAttacking.Position); + } + } + + #endregion + } + + public void PlayAnimationOnce(MovementState animation, TimeSpan duration) + { + Sprite.ForEach(e => e.PlayOnce(animation, duration)); + } + + /// + /// Draw the creature on the screen. + /// + /// Sprite batch used for drawing. + public void Draw(SpriteBatch spriteBatch) + { + if (IsSelected) DrawSelection(spriteBatch); + Sprite.ForEach(e => e?.Draw(spriteBatch, Position, MovementState, MovementDirection)); + if (IsSelected) DrawLifeRectangle(spriteBatch); + foreach (var arrow in mArrowList) + { + arrow.DrawArrow(spriteBatch); + } + } + + public void DrawStatic(SpriteBatch spriteBatch, Point position) + { + Sprite.ForEach(e => e?.DrawStatic(spriteBatch, position, MovementState.Idle, MovementDirection.S)); + } + + protected virtual void Die() + { + if (Faction == Faction.Plebs || Faction == Faction.Kingdom) + { + mAchievementsAndStatistics.mHundredDeadCorpses += 1; + mAchievementsAndStatistics.mUndeadArmy += 1; + mAchievementsAndStatistics.mRightHandOfDeath += 1; + mAchievementsAndStatistics.mKilledCreatures += 1; + } + else if (Faction == Faction.Undead) + { + mAchievementsAndStatistics.mLostServants += 1; + } + mIsDead = true; + Life = 0; + MovementState = MovementState.Dying; + } + + private void DrawSelection(SpriteBatch spriteBatch) + { + // TODO: Remove the magic vector and adjust position. + spriteBatch.Draw(mSelectionTexture, Position - new Vector2(32, 16), SelectionColor); + /* + spriteBatch.Draw(mOnePixelTexture, new Rectangle(BoundaryRectangle.X, BoundaryRectangle.Y, BoundaryRectangle.Width, 2), SelectionColor); + spriteBatch.Draw(mOnePixelTexture, new Rectangle(BoundaryRectangle.X, BoundaryRectangle.Y + BoundaryRectangle.Height, BoundaryRectangle.Width, 2), SelectionColor); + spriteBatch.Draw(mOnePixelTexture, new Rectangle(BoundaryRectangle.X, BoundaryRectangle.Y, 2, BoundaryRectangle.Height), SelectionColor); + spriteBatch.Draw(mOnePixelTexture, new Rectangle(BoundaryRectangle.X + BoundaryRectangle.Width, BoundaryRectangle.Y, 2, BoundaryRectangle.Height), SelectionColor); + */ + } + + private void DrawLifeRectangle(SpriteBatch spriteBatch) + { + var backgroundRectangle = new Rectangle(SelectionRectangle.X, SelectionRectangle.Y - 12, SelectionRectangle.Width, SelectionRectangle.Height / 10); + var lifeBarRectangle = new Rectangle(SelectionRectangle.X + 2, SelectionRectangle.Y - 11, SelectionRectangle.Width - 3, SelectionRectangle.Height / 10 - 2); + spriteBatch.Draw(mOnePixelTexture, backgroundRectangle, Color.Black * 0.7f); + spriteBatch.Draw(mOnePixelTexture, new Rectangle(lifeBarRectangle.X, lifeBarRectangle.Y, lifeBarRectangle.Width * Life / MaxLife, lifeBarRectangle.Height), Color.Firebrick); + } + + /// + /// Change the equipment/sprite of the creature to something other. + /// + /// Which part of the equipment should be changed. + /// Which sprite to use instead. + public void ChangeEquipment(EquipmentType equipmentType, ISpriteCreature sprite) + { + if (Sprite.Length > (int) equipmentType) + { + sprite.Load(mContentManager); + Sprite[(int)equipmentType] = sprite; + } +#if DEBUG + else + { + throw new Exception("Creature does not have a " + equipmentType.ToString() + " slot. For further information talk to Thomas."); + } +#endif + } + + /// + /// Returns the object instance without modifications. + /// + /// This object. + public virtual IGameObject GetSelf() + { + return this; + } + + public void ResetPosition() + { + Position = InitialPosition; + } + + #region Compute Move Distance + /// + /// Returns vector for the moving distance to attack. + /// + /// Vector. + private Vector2 ComputeMoVector(IGameObject gameObject) + { + Vector2 goToPosition = new Vector2(Position.X, Position.Y); + + /* + * P + * D + * + */ + if (Position.X <= gameObject.BoundaryRectangle.Left && + Position.Y <= gameObject.BoundaryRectangle.Top) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Left - AttackRadius * 0.5f, + gameObject.BoundaryRectangle.Top - AttackRadius * 0.5f); + } + /* + * P + * D + * + */ + if (Position.X >= gameObject.BoundaryRectangle.Left && + Position.X <= gameObject.BoundaryRectangle.Right && + Position.Y <= gameObject.BoundaryRectangle.Top) + { + goToPosition = new Vector2(Position.X, + gameObject.BoundaryRectangle.Top - AttackRadius * 0.5f); + } + /* + * P + * D + * + */ + if (Position.X >= gameObject.BoundaryRectangle.Right && + Position.Y <= gameObject.BoundaryRectangle.Top) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Right - AttackRadius * 0.5f, + gameObject.BoundaryRectangle.Top - AttackRadius * 0.5f); + } + /* + * + * D P + * + */ + if (Position.X >= gameObject.BoundaryRectangle.Right && + Position.Y <= gameObject.BoundaryRectangle.Bottom && + Position.Y >= gameObject.BoundaryRectangle.Top) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Right - AttackRadius * 0.5f, + Position.Y); + } + /* + * + * D + * P + */ + if (Position.X >= gameObject.BoundaryRectangle.Right && + Position.Y >= gameObject.BoundaryRectangle.Bottom) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Right - AttackRadius * 0.5f, + gameObject.BoundaryRectangle.Bottom - AttackRadius * 0.5f); + } + /* + * + * D + * P + */ + if (Position.X >= gameObject.BoundaryRectangle.Left && + Position.X <= gameObject.BoundaryRectangle.Right && + Position.Y >= gameObject.BoundaryRectangle.Bottom) + { + goToPosition = new Vector2(Position.X, + gameObject.BoundaryRectangle.Bottom - AttackRadius * 0.5f); + } + /* + * + * D + * P + */ + if (Position.X <= gameObject.BoundaryRectangle.Left && + Position.Y >= gameObject.BoundaryRectangle.Bottom) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Left - AttackRadius * 0.5f, + gameObject.BoundaryRectangle.Bottom - AttackRadius * 0.5f); + } + /* + * + * P D + * + */ + if (Position.X <= gameObject.BoundaryRectangle.Left && + Position.Y <= gameObject.BoundaryRectangle.Bottom && + Position.Y >= gameObject.BoundaryRectangle.Top) + { + goToPosition = + new Vector2(gameObject.BoundaryRectangle.Left - AttackRadius * 0.5f, + Position.Y); + } + + return goToPosition; + } + #endregion + + public override bool Equals(Object obj) + { + if (obj == null) + return false; + if (obj == this) + return true; + if (!(obj is IGameObject)) + return false; + return Id.Equals(((IGameObject) obj).Id); + } + + public override int GetHashCode() + { + return Id; + } + + /// + /// Returns synchronized random value. + /// + /// Vector. + /// Lower bound for random value. + /// Upper bound +1 for random value. + private static int RandomNumber(int min, int max) + { + // synchronize + lock (sYncLock) + { + return sRandom.Next(min, max); + } + } + + public void Heal(int amount) + { + if (Life + amount < MaxLife) + { + Life += amount; + } + else + { + Life = MaxLife; + } + } + + public void Empower(int modifier) + { + MaxLife *= modifier; + Life *= modifier; + } + + private void CreateArrow(Vector2 start, Vector2 goal) + { + if (mArrowList.Count >= 60) mArrowList.Clear(); + Arrow arrow = new Arrow(start, goal); + arrow.LoadArrow(mContentManager); + mArrowList.Add(arrow); + } + + /// + /// Save this creature’s data to a CreatureData object. + /// + /// the CreatureData object with the status of this creature + public virtual CreatureData SaveData() + { + var creatureData = new CreatureData(); + creatureData.Type = Type; + creatureData.Id = Id; + creatureData.Life = Life; + creatureData.MaxLife = MaxLife; + creatureData.Attack = Attack; + creatureData.Recovery = Recovery; + creatureData.IsUpgraded = IsUpgraded; + creatureData.PositionX = Position.X; + creatureData.PositionY = Position.Y; + creatureData.MovementDirection = MovementDirection; + creatureData.MovementState = MovementState; + creatureData.MovementData = MovementScheme.SaveData(); + // references + if (IsAttacking != null) + creatureData.IsAttackingId = IsAttacking.Id; + return creatureData; + } + + /// + /// Restore the creature's state from the given data. + /// + /// the state of the creature to restore + public virtual void LoadData(CreatureData creatureData) + { + // ID is set by IdGenerator.SetIdOnce + Life = creatureData.Life; + MaxLife = creatureData.MaxLife; + Attack = creatureData.Attack; + Recovery = creatureData.Recovery; + IsUpgraded = creatureData.IsUpgraded; + Position = new Vector2(creatureData.PositionX, creatureData.PositionY); + MovementDirection = creatureData.MovementDirection; + MovementState = creatureData.MovementState; + MovementScheme.LoadData(creatureData.MovementData); + + if (Life <= 0) + Die(); + } + + /// + /// Restore the creature's references to other creatures from the given data. + /// + /// the state of the creature to restore + /// the list of all creatures by ID + public virtual void LoadReferences(CreatureData data, Dictionary creatures) + { + if (creatures.ContainsKey(data.IsAttackingId)) + IsAttacking = creatures[data.IsAttackingId]; + } + } +} diff --git a/V3/Objects/Arrow.cs b/V3/Objects/Arrow.cs new file mode 100644 index 0000000..57200b2 --- /dev/null +++ b/V3/Objects/Arrow.cs @@ -0,0 +1,109 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + public sealed class Arrow + { + //Drawing an arrow + private const int SpeedModifier = 10; + private readonly ArrowSprite mArrow; + private Vector2 mArrowPosition; + private Vector2 mArrowGoal; + private Vector2 mDirection; + private bool mArrowDraw; + private readonly MovementDirection mMovementDirection; + + public Arrow(Vector2 start, Vector2 goal) + { + mArrowPosition = start; + mArrowGoal = goal; + mDirection = goal - start; + mDirection.Normalize(); + mMovementDirection = GiveMovementDirection(mDirection); + mArrow = new ArrowSprite(); + mArrowDraw = true; + } + + public void LoadArrow(ContentManager contentManager) + { + mArrow.Load(contentManager); + } + + public void DrawArrow(SpriteBatch spriteBatch) + { + if (mArrowDraw) + mArrow.Draw(spriteBatch, mArrowPosition, MovementState.Idle, mMovementDirection); + } + + /// + /// The moving for arrow + /// + public void UpdateArrow() + { + if (mArrowDraw) + mArrowPosition += mDirection * SpeedModifier; + + if (Vector2.Distance(mArrowPosition, mArrowGoal) < 1f * SpeedModifier) + mArrowDraw = false; + } + + /// + /// Calculates the direction the creature is looking when moving. + /// Method copied from PlayerMovement class. + /// + private MovementDirection GiveMovementDirection(Vector2 direction) + { + // |\ + // |α\ α == 22.5° + // b| \ 1 β == 67.5° + // | β\ + // ────── + // a + const float b = 0.92f; // b == sin β + const float a = 0.38f; // a == sin α + MovementDirection movementDirection; + if (direction.X < -b) + { + movementDirection = MovementDirection.W; + } + else if (direction.X > b) + { + movementDirection = MovementDirection.O; + } + else if (direction.Y > 0) + { + if (direction.X < -a) + { + movementDirection = MovementDirection.SW; + } + else if (direction.X > a) + { + movementDirection = MovementDirection.SO; + } + else + { + movementDirection = MovementDirection.S; + } + } + else + { + if (direction.X < -a) + { + movementDirection = MovementDirection.NW; + } + else if (direction.X > a) + { + movementDirection = MovementDirection.NO; + } + else + { + movementDirection = MovementDirection.N; + } + } + return movementDirection; + } + } +} diff --git a/V3/Objects/BuildingState.cs b/V3/Objects/BuildingState.cs new file mode 100644 index 0000000..79c621e --- /dev/null +++ b/V3/Objects/BuildingState.cs @@ -0,0 +1,8 @@ +// ReSharper disable InconsistentNaming +namespace V3.Objects +{ + public enum BuildingFace + { + SW, NO + } +} \ No newline at end of file diff --git a/V3/Objects/Castle.cs b/V3/Objects/Castle.cs new file mode 100644 index 0000000..fd04ddd --- /dev/null +++ b/V3/Objects/Castle.cs @@ -0,0 +1,15 @@ +using Microsoft.Xna.Framework; + +namespace V3.Objects +{ + public sealed class Castle : AbstractBuilding + { + public override string Name { get; } = "Burg"; + protected override int MaxRobustness { get; } = 800; + public override int Robustness { get; protected set; } = 800; + + public Castle(Vector2 position, Rectangle size, string textureName, BuildingFace facing) : base(position, size, textureName, facing) + { + } + } +} diff --git a/V3/Objects/CreatureFactory.cs b/V3/Objects/CreatureFactory.cs new file mode 100644 index 0000000..238ea41 --- /dev/null +++ b/V3/Objects/CreatureFactory.cs @@ -0,0 +1,127 @@ +using System; +using Microsoft.Xna.Framework; +using V3.Data; + +namespace V3.Objects +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class CreatureFactory + { + private readonly IBasicCreatureFactory mFactory; + private readonly Random mRnd = new Random(); + + public CreatureFactory(IBasicCreatureFactory factory) + { + mFactory = factory; + } + + public ICreature CreateCreature(CreatureType type, int id) + { + IdGenerator.SetIdOnce(id); + switch (type) + { + case CreatureType.FemalePeasant: + return mFactory.CreateFemalePeasant(); + case CreatureType.King: + return mFactory.CreateKing(); + case CreatureType.KingsGuard: + return mFactory.CreateKingsGuard(); + case CreatureType.Knight: + return mFactory.CreateKnight(); + case CreatureType.MalePeasant: + return mFactory.CreateMalePeasant(); + case CreatureType.Meatball: + return mFactory.CreateMeatball(); + case CreatureType.Necromancer: + return mFactory.CreateNecromancer(); + case CreatureType.Prince: + return mFactory.CreatePrince(); + case CreatureType.Skeleton: + return mFactory.CreateSkeleton(); + case CreatureType.Zombie: + return mFactory.CreateZombie(); + default: + IdGenerator.ClearIdOnce(); + return null; + } + } + + public MalePeasant CreateMalePeasant(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateMalePeasant(), position, movementDirection); + } + + public FemalePeasant CreateFemalePeasant(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateFemalePeasant(), position, movementDirection); + } + + public Necromancer CreateNecromancer(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateNecromancer(), position, movementDirection); + } + + public Skeleton CreateSkeleton(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateSkeleton(), position, movementDirection); + } + + public SkeletonElite CreateSkeletonElite(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateSkeletonElite(), position, movementDirection); + } + + public Zombie CreateZombie(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateZombie(), position, movementDirection); + } + + public Knight CreateKnight(Vector2 position, MovementDirection movementDirection) + { + Knight knight = CreateCreature(mFactory.CreateKnight(), position, movementDirection); + if (mRnd.Next(3) == 0) + { + knight.MakeFemale(); + } + return knight; + } + + public KingsGuard CreateKingsGuard(Vector2 position, MovementDirection movementDirection) + { + KingsGuard guard = CreateCreature(mFactory.CreateKingsGuard(), position, movementDirection); + if (mRnd.Next(3) == 0) + { + guard.MakeFemale(); + } + return guard; + } + + public SkeletonHorse CreateSkeletonHorse(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateSkeletonHorse(), position, movementDirection); + } + + public Meatball CreateMeatball(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateMeatball(), position, movementDirection); + } + + public Prince CreatePrince(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreatePrince(), position, movementDirection); + } + + public King CreateKing(Vector2 position, MovementDirection movementDirection) + { + return CreateCreature(mFactory.CreateKing(), position, movementDirection); + } + + private T CreateCreature(T creature, Vector2 position, MovementDirection movementDirection) where T: ICreature + { + creature.Position = position; + creature.InitialPosition = position; + creature.MovementDirection = movementDirection; + return creature; + } + } +} diff --git a/V3/Objects/FemalePeasant.cs b/V3/Objects/FemalePeasant.cs new file mode 100644 index 0000000..855685c --- /dev/null +++ b/V3/Objects/FemalePeasant.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// Class for simple peasants which will be transformed into zombies. + /// + public sealed class FemalePeasant : AbstractCreature + { + public override string Name { get; protected set; } = "Dorfbewohnerin"; + public override int Life { get; protected set; } = 20; + public override int MaxLife { get; protected set; } = 20; + public override int Speed { get; } = 10; + public override int Attack { get; protected set; } = 5; + public override int AttackRadius { get; protected set; } = 0; + public override int SightRadius { get; protected set; } = 20; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.3); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new ClothFemaleSprite(), new HeadFemaleSprite(), null}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.FemalePeasant; + public override Faction Faction { get; } = Faction.Plebs; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + + public FemalePeasant(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + public void RemoveArmor() + { + if (Sprite[0] is NudeFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new ClothFemaleSprite()); + } + else if (Sprite[0] is ClothFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeFemaleSprite()); + } + } + } +} diff --git a/V3/Objects/Forge.cs b/V3/Objects/Forge.cs new file mode 100644 index 0000000..1da3970 --- /dev/null +++ b/V3/Objects/Forge.cs @@ -0,0 +1,19 @@ +using Microsoft.Xna.Framework; + +namespace V3.Objects +{ + /// + /// A Forge which can be attacked. + /// + public sealed class Forge : AbstractBuilding + { + public override string Name { get; } = "Schmiede"; + protected override int MaxRobustness { get; } = 200; + public override int Robustness { get; protected set; } = 200; + public override int MaxGivesWeapons { get; protected set; } = 10; + + public Forge(Vector2 position, Rectangle size, string textureName, BuildingFace facing) : base(position, size, textureName, facing) + { + } + } +} diff --git a/V3/Objects/IBasicCreatureFactory.cs b/V3/Objects/IBasicCreatureFactory.cs new file mode 100644 index 0000000..9b7a88b --- /dev/null +++ b/V3/Objects/IBasicCreatureFactory.cs @@ -0,0 +1,28 @@ +namespace V3.Objects +{ + public interface IBasicCreatureFactory + { + MalePeasant CreateMalePeasant(); + + FemalePeasant CreateFemalePeasant(); + + Necromancer CreateNecromancer(); + + Skeleton CreateSkeleton(); + SkeletonElite CreateSkeletonElite(); + + Zombie CreateZombie(); + + Knight CreateKnight(); + + SkeletonHorse CreateSkeletonHorse(); + + Meatball CreateMeatball(); + + Prince CreatePrince(); + + King CreateKing(); + + KingsGuard CreateKingsGuard(); + } +} diff --git a/V3/Objects/IBuilding.cs b/V3/Objects/IBuilding.cs new file mode 100644 index 0000000..0fdd0aa --- /dev/null +++ b/V3/Objects/IBuilding.cs @@ -0,0 +1,20 @@ +namespace V3.Objects +{ + public interface IBuilding : IGameObject + { + int Robustness { get; } + string Name { get; } + int MaxGivesWeapons { get; } + + /// + /// Building takes specific amount of damage. Substracted from Robustness. + /// + /// TakeDamage taken + void TakeDamage(int damage); + + /// + /// Building can give a fixed amount of upgrades. + /// + void UpgradeCounter(); + } +} diff --git a/V3/Objects/ICreature.cs b/V3/Objects/ICreature.cs new file mode 100644 index 0000000..891ada7 --- /dev/null +++ b/V3/Objects/ICreature.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Data; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// A moving game object. + /// + public interface ICreature : IGameObject + { + string Name { get; } + Vector2 InitialPosition { set; } + int Life { get; } + int MaxLife { get; } + int Speed { get; } + int Attack { get; } + int AttackRadius { get; } + int SightRadius { get; } + TimeSpan TotalRecovery { get; } + TimeSpan Recovery { get; set; } + /// + /// Area where the creature is standing. Used for collisions. + /// + /// + /// Where you can click to select the creature. + /// + Rectangle SelectionRectangle { get; } + bool IsSelected { get; set; } + ICreature IsAttacking { get; set; } + IBuilding IsAttackingBuilding { get; set; } + MovementDirection MovementDirection { get; set; } + MovementState MovementState { get; set; } + Faction Faction { get; } + bool IsDead { get; } + bool IsUpgraded { get; set; } + + /// + /// Creature takes specific amount of damage. Substracted from Life. + /// + /// TakeDamage taken. + void TakeDamage(int damage); + + /// + /// Give command to move to desired destination. Not instant movement. + /// + /// Destination in pixels. + void Move (Vector2 destination); + + //void ImportentMove(IGameObject creature); + + /// + /// Draws a static non-animated sprite (for HUD) at specified position. + /// + /// Sprite batch used for drawing. + /// Position where to draw the sprite. + void DrawStatic(SpriteBatch spriteBatch, Point position); + + /// + /// Update the creature behaviour and animation. + /// + void Update(GameTime gameTime, ICreature playerCharacter, + bool rightButtonPressed, Vector2 rightButtonPosition, Quadtree quadtree, ICamera camera); + + /// + /// Change the equipment/sprite of the creature to something other. + /// If in debug mode the function throws an exception if the creature does not have the specified equipment slots. + /// + /// Which part of the equipment should be changed. + /// Which sprite to use instead. + void ChangeEquipment(EquipmentType equipmentType, ISpriteCreature sprite); + + /// + /// Sets back the position of the creature to its state when created. + /// + void ResetPosition(); + + /// + /// Plays the specified animation fully, but only once. + /// + /// For which movement state the animation should be played. + /// How long (or how slow) should the animation be? + void PlayAnimationOnce(MovementState animation, TimeSpan duration); + + /// + /// Heals the creature. Can not go over MaxLife. + /// + /// How much HP the creature gains. + void Heal(int amount); + + /// + /// Creature gets more life and maxlife. Used for testing in Techdemo. + /// + /// Multiplyier for Life. + void Empower(int modifier); + + /// + /// Save this creature’s data to a CreatureData object. + /// + /// the CreatureData object with the status of this creature + CreatureData SaveData(); + + /// + /// Restore the creature's state from the given data. + /// + /// the state of the creature to restore + void LoadData(CreatureData data); + + /// + /// Restore the creature's references to other creatures from the given data. + /// + /// the state of the creature to restore + /// the list of all creatures by ID + void LoadReferences(CreatureData data, Dictionary creatures); + } +} diff --git a/V3/Objects/IGameObject.cs b/V3/Objects/IGameObject.cs new file mode 100644 index 0000000..556e918 --- /dev/null +++ b/V3/Objects/IGameObject.cs @@ -0,0 +1,43 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects +{ + /// + /// A game object which is placed on the map. + /// + public interface IGameObject + { + Vector2 Position { get; set; } + + /// + /// A unique ID for this game object, with which it can be identified. + /// All implementations should use the IdGenerator to generate this ID. + /// + int Id { get; } + + /// + /// Draws the game object on the screen. + /// + /// Sprite batch used for drawing. + void Draw(SpriteBatch spriteBatch); + + /// + /// The size of the object. + /// + Rectangle BoundaryRectangle { get; } + + /// + /// Loads needed graphics. + /// + /// Content manager used. + void LoadContent(ContentManager contentManager); + + /// + /// Returns the object instance without modifications. + /// + /// This object. + IGameObject GetSelf(); + } +} diff --git a/V3/Objects/IObjectsManager.cs b/V3/Objects/IObjectsManager.cs new file mode 100644 index 0000000..e8fa17b --- /dev/null +++ b/V3/Objects/IObjectsManager.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Map; + +namespace V3.Objects +{ + /// + /// Objects manager for all game objects, be is creatures or buildings or even simple landscape objects. + /// + public interface IObjectsManager + { + //***** FOR TESTING PURPOSES! + List AddToSelectables { get; } + List CreatureList { get; } + List UndeadCreatures { get; } + //List KingdromCreatures { get; } + //List PlebCreatures { get; } + //***** NOT FOR TESTING PURPOSES ANYMORE! + + /// + /// Gets the current player character. Usually the necromancer. + /// Do not set directly! Use CreatePlayerCharacter() instead! + /// + ICreature PlayerCharacter { get; } + + ICreature Boss { get; } + + ICreature Prince { get; } + + Castle Castle { get; } + + /// + /// If you load a new map with new objects you need to initialize the objects manager again. + /// (Or else you have all the current objects on the new map.) + /// + /// + void Initialize(IMapManager mapManager); + + /// + /// Removes all objects from the object manager. + /// + void Clear(); + + /// + /// Creates the player character. This should be the first thing you do + /// after you created or initialized the objects manager. + /// + /// + void CreatePlayerCharacter(Necromancer necromancer); + + /// + /// Creates the boss of the level. Game is won if the boss is killed. + /// + /// Some ICreature to kill for winning. + void CreateBoss(ICreature boss); + + /// + /// Create the prince, a small boss. + /// + /// Some hard ICreature to kill. + void CreatePrince(ICreature prince); + + /// + /// Creates a creature for the game and inserts it in the appropriate data structures. + /// + /// + void CreateCreature(ICreature creature); + + /// + /// Removes specified creature from the game. + /// + /// The creature to be removed. + void RemoveCreature(ICreature creature); + + /// + /// Draws all currently shown objects on the map. + /// + /// The sprite batch used. + /// Camera for calculating which objects need to be drawn. + void Draw(SpriteBatch spriteBatch, ICamera camera); + + /// + /// Draws a visual representation of the Quadtree. For debugging purposes. + /// + /// + void DrawQuadtree(SpriteBatch spriteBatch); + + /// + /// Update the behaviour of all creatures on the map. + /// + /// Current game time. + /// Did the player press the right mouse button? + /// Where is the mouse currently? + /// Camera for checking where to do important updates. + void Update(GameTime gameTime, bool rightButtonPressed, Vector2 rightButtonPosition, ICamera camera); + + /// + /// Imports the TextureObjects from the objects map layer for drawing things in the right order. + /// + /// + void ImportMapObjects(List textureObjects); + + /// + /// Get all objects in the given rectangles. + /// + /// The rectangle which defines the area of the returnes objects. + /// Game objects in the rectangle. + List GetObjectsInRectangle(Rectangle rectangle); + + /// + /// Gets all creatures which are in the given ellipse area. + /// + /// To check if creature is in ellipse area. + /// + List GetCreaturesInEllipse(Ellipse ellipse); + + /// + /// Playing around with some cheating codes. + /// + void ExposeTheLiving(); + + /// + /// Checks if a creature is standing in a graveyard area. + /// + /// Check for this creature. + /// True when standing in graveyard area. + bool InGraveyardArea(ICreature creature); + } +} diff --git a/V3/Objects/IdGenerator.cs b/V3/Objects/IdGenerator.cs new file mode 100644 index 0000000..08976ca --- /dev/null +++ b/V3/Objects/IdGenerator.cs @@ -0,0 +1,59 @@ +using System; + +namespace V3.Objects +{ + /// + /// Static helper class that generates unique IDs for game objects. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class IdGenerator + { + private static int sCurrentId; + + private static int? sIdOnce; + + private IdGenerator() + { + throw new NotImplementedException(); + } + + /// + /// Get an ID for a new game object. + /// + /// the ID to use for a new game object + public static int GetNextId() + { + int id; + if (sIdOnce.HasValue) + { + id = sIdOnce.Value; + ClearIdOnce(); + } + else + { + id = sCurrentId; + sCurrentId++; + } + + return id; + } + + /// + /// Sets the ID to use only for the next object that is created. + /// + /// the id for the next object + public static void SetIdOnce(int id) + { + sIdOnce = id; + } + + /// + /// Clear the ID stored by SetIdOnce that is used only for the + /// next object. + /// + public static void ClearIdOnce() + { + sIdOnce = null; + } + } +} diff --git a/V3/Objects/King.cs b/V3/Objects/King.cs new file mode 100644 index 0000000..b1c9713 --- /dev/null +++ b/V3/Objects/King.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + // ReSharper disable once ClassNeverInstantiated.Global + public class King : AbstractCreature + { + public override string Name { get; protected set; } = "König Harry"; + public override int Life { get; protected set; } = 10000; + public override int MaxLife { get; protected set; } = 10000; + public override int Speed { get; } = 10; + public override int Attack { get; protected set; } = 45; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 500; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.8); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = { new KingSprite() }; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.King; + public override Faction Faction { get; } = Faction.Kingdom; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public King(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + } +} diff --git a/V3/Objects/KingsGuard.cs b/V3/Objects/KingsGuard.cs new file mode 100644 index 0000000..a0f3bc5 --- /dev/null +++ b/V3/Objects/KingsGuard.cs @@ -0,0 +1,62 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + public sealed class KingsGuard : AbstractCreature + { + public override string Name { get; protected set; } = "Königliche Garde"; + public override int Life { get; protected set; } = 200; + public override int MaxLife { get; protected set; } = 200; + public override int Speed { get; } = 7; + public override int Attack { get; protected set; } = 25; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 200; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.5); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = { new PlateSprite(), new HeadPlateSprite(), new LongswordSprite(), new ShieldSprite() }; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.KingsGuard; + public override Faction Faction { get; } = Faction.Kingdom; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public KingsGuard(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager,achievementsAndStatistics) + { + } + + public void MakeFemale() + { + ChangeEquipment(EquipmentType.Body, new PlateFemaleSprite()); + ChangeEquipment(EquipmentType.Head, new HeadPlateFemaleSprite()); + ChangeEquipment(EquipmentType.Weapon, new LongswordFemaleSprite()); + ChangeEquipment(EquipmentType.Offhand, new ShieldFemaleSprite()); + } + + public void RemoveArmor() + { + if (Sprite[(int)EquipmentType.Body] is PlateSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeSprite()); + } + else if (Sprite[(int)EquipmentType.Body] is PlateFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeFemaleSprite()); + } + else if (Sprite[(int)EquipmentType.Body] is NudeSprite) + { + ChangeEquipment(EquipmentType.Body, new PlateSprite()); + } + else if (Sprite[(int)EquipmentType.Body] is NudeFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new PlateFemaleSprite()); + } + } + } +} diff --git a/V3/Objects/Knight.cs b/V3/Objects/Knight.cs new file mode 100644 index 0000000..ef31f2a --- /dev/null +++ b/V3/Objects/Knight.cs @@ -0,0 +1,65 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// A knight which fights against the necromancer. + /// + public sealed class Knight : AbstractCreature + { + public override string Name { get; protected set; } = "Ritter"; + public override int Life { get; protected set; } = 120; + public override int MaxLife { get; protected set; } = 120; + public override int Speed { get; } = 8; + public override int Attack { get; protected set; } = 15; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 200; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.5); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new ChainSprite(), new HeadChainSprite(), new ShortswordSprite(), new BucklerSprite()}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.Knight; + public override Faction Faction { get; } = Faction.Kingdom; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public Knight(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + public void MakeFemale() + { + ChangeEquipment(EquipmentType.Body, new ChainFemaleSprite()); + ChangeEquipment(EquipmentType.Head, new HeadChainFemaleSprite()); + ChangeEquipment(EquipmentType.Weapon, new ShortswordFemaleSprite()); + ChangeEquipment(EquipmentType.Offhand, new BucklerFemaleSprite()); + } + + public void RemoveArmor() + { + if (Sprite[(int) EquipmentType.Body] is ChainSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeSprite()); + } + else if (Sprite[(int) EquipmentType.Body] is ChainFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeFemaleSprite()); + } + else if (Sprite[(int)EquipmentType.Body] is NudeSprite) + { + ChangeEquipment(EquipmentType.Body, new ChainSprite()); + } + else if (Sprite[(int)EquipmentType.Body] is NudeFemaleSprite) + { + ChangeEquipment(EquipmentType.Body, new ChainFemaleSprite()); + } + } + } +} diff --git a/V3/Objects/MalePeasant.cs b/V3/Objects/MalePeasant.cs new file mode 100644 index 0000000..1250412 --- /dev/null +++ b/V3/Objects/MalePeasant.cs @@ -0,0 +1,49 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// Class for simple peasants which will be transformed into zombies. + /// + public sealed class MalePeasant : AbstractCreature + { + public override string Name { get; protected set; } = "Dorfbewohner"; + public override int Life { get; protected set; } = 24; + public override int MaxLife { get; protected set; } = 24; + public override int Speed { get; } = 10; + public override int Attack { get; protected set; } = 5; + public override int AttackRadius { get; protected set; } = 0; + public override int SightRadius { get; protected set; } = 20; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.3); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new ClothSprite(), new HeadSprite(), null}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.MalePeasant; + public override Faction Faction { get; } = Faction.Plebs; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public MalePeasant(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + public void RemoveArmor() + { + if (Sprite[0] is NudeSprite) + { + ChangeEquipment(EquipmentType.Body, new ClothSprite()); + } + else if (Sprite[0] is ClothSprite) + { + ChangeEquipment(EquipmentType.Body, new NudeSprite()); + } + } + } +} diff --git a/V3/Objects/Meatball.cs b/V3/Objects/Meatball.cs new file mode 100644 index 0000000..144ef90 --- /dev/null +++ b/V3/Objects/Meatball.cs @@ -0,0 +1,36 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + public sealed class Meatball : AbstractCreature + { + public Meatball(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + protected override ISpriteCreature[] Sprite { get; } = { new MeatballSprite() }; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.Meatball; + public override string Name { get; protected set; } = "Fleischball"; + public override int Life { get; protected set; } = 200; + public override int MaxLife { get; protected set; } = 200; + public override int Speed { get; } = 5; + public override int Attack { get; protected set; } = 70; + public override int AttackRadius { get; protected set; } = 60; + public override int SightRadius { get; protected set; } = 100; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(1); + public override TimeSpan Recovery { get; set; } + public override Faction Faction { get; } = Faction.Undead; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + protected override Point CreatureSize { get; } = new Point(36); + protected override Point BoundaryShift { get; } = new Point(-18, -24); + } +} diff --git a/V3/Objects/Movement.cs b/V3/Objects/Movement.cs new file mode 100644 index 0000000..3dfa01b --- /dev/null +++ b/V3/Objects/Movement.cs @@ -0,0 +1,20 @@ +// ReSharper disable InconsistentNaming +namespace V3.Objects +{ + /// + /// Cardinal directions to show where the specific creature is facing. + /// Because of the isometric viewpoint N(orth) is the upper right. + /// + public enum MovementDirection + { + W, NW, N, NO, O, SO, S, SW + } + + /// + /// The basic movement states a creature must hold. + /// + public enum MovementState + { + Idle, Moving, Attacking, Dying, Special + } +} \ No newline at end of file diff --git a/V3/Objects/Movement/CountStepsMovement.cs b/V3/Objects/Movement/CountStepsMovement.cs new file mode 100644 index 0000000..e8c24c4 --- /dev/null +++ b/V3/Objects/Movement/CountStepsMovement.cs @@ -0,0 +1,16 @@ +using Microsoft.Xna.Framework; + +namespace V3.Objects.Movement +{ + public class CountStepsMovement : PlayerMovement + { + public float WalkedPixels { get; private set; } + + public override Vector2 GiveNewPosition(Vector2 currentPosition, int speed) + { + var movedDistance = base.GiveNewPosition(currentPosition, speed); + WalkedPixels += Vector2.Distance(currentPosition, currentPosition + movedDistance); + return movedDistance; + } + } +} \ No newline at end of file diff --git a/V3/Objects/Movement/IMovable.cs b/V3/Objects/Movement/IMovable.cs new file mode 100644 index 0000000..659708b --- /dev/null +++ b/V3/Objects/Movement/IMovable.cs @@ -0,0 +1,43 @@ +using Microsoft.Xna.Framework; +using V3.Data; +using V3.Map; + +namespace V3.Objects.Movement +{ + public interface IMovable + { + /// + /// Calculates a path without collisions to desired destination. + /// + /// Pathfinder to use. + /// Current position in pixel. + /// Destination in pixel. + void FindPath(Pathfinder pathfinder, Vector2 position, Vector2 destination); + + /// + /// Uses pathfinder to for steady movement to new transition. + /// + /// Current position in pixel. + /// Movement speed of the creature. + /// Normalized vector * speed which represents a small step in the direction of desired destination.( + Vector2 GiveNewPosition(Vector2 currentPosition, int speed); + + /// + /// Calculates the direction the creature is looking when moving. + /// + MovementDirection GiveMovementDirection(); + bool IsMoving { get; } + + /// + /// Save the movement data to a MovementData object. + /// + /// the MovementData object with the current status + MovementData SaveData(); + + /// + /// Restore the movement state from the given data. + /// + /// the state of the movement to restore + void LoadData(MovementData movementData); + } +} diff --git a/V3/Objects/Movement/PlayerMovement.cs b/V3/Objects/Movement/PlayerMovement.cs new file mode 100644 index 0000000..326503f --- /dev/null +++ b/V3/Objects/Movement/PlayerMovement.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using V3.Data; +using V3.Map; + +namespace V3.Objects.Movement +{ + // TODO: Rename the class. Current name is unfitting. (But what is fitting?) + /// + /// Movement scheme for moving an object with the pathfinder. + /// + public class PlayerMovement : IMovable + { + private const int CellHeight = Constants.CellHeight; + private const int CellWidth = Constants.CellWidth; + private const float SpeedModifier = 0.25f; + + private List mPath; + private int mStep; + private Vector2 mLastMovement; + + public bool IsMoving { get; private set; } + + /// + /// Calculates a path without collisions to desired destination. + /// + /// Pathfinder to use. + /// Current position in pixel. + /// Destination in pixel. + public void FindPath(Pathfinder pathfinder, Vector2 position, Vector2 destination) + { + mStep = 0; + mPath = pathfinder.FindPath(new Vector2((int)(position.X / CellWidth), (int)(position.Y / CellHeight)), + new Vector2((int)(destination.X / CellWidth), (int)(destination.Y / CellHeight))); + IsMoving = mPath.Count > 0; + } + + /// + /// Uses pathfinder to for steady movement to new transition. + /// + /// Current position in pixel. + /// Movement speed of the creature. + /// Normalized vector * speed which represents a small step in the direction of desired destination.( + public virtual Vector2 GiveNewPosition(Vector2 currentPosition, int speed) + { + Vector2 nextPosition = mPath[mStep]; + Vector2 newPosition = nextPosition - currentPosition; + newPosition.Normalize(); + float distanceToDestination = Vector2.Distance(nextPosition, currentPosition); + if (distanceToDestination < SpeedModifier * speed) + { + if (mStep == mPath.Count - 1) + { + IsMoving = false; + } + else + { + mStep++; + } + } + mLastMovement = newPosition; + return newPosition * SpeedModifier * speed; + } + + /// + /// Calculates the direction the creature is looking when moving. + /// + public MovementDirection GiveMovementDirection() + { + // |\ + // |α\ α == 22.5° + // b| \ 1 β == 67.5° + // | β\ + // ────── + // a + const float b = 0.92f; // b == sin β + const float a = 0.38f; // a == sin α + Vector2 direction = mLastMovement; + MovementDirection movementDirection; + if (direction.X < -b) + { + movementDirection = MovementDirection.W; + } + else if (direction.X > b) + { + movementDirection = MovementDirection.O; + } + else if (direction.Y > 0) + { + if (direction.X < -a) + { + movementDirection = MovementDirection.SW; + } + else if (direction.X > a) + { + movementDirection = MovementDirection.SO; + } + else + { + movementDirection = MovementDirection.S; + } + } + else + { + if (direction.X < -a) + { + movementDirection = MovementDirection.NW; + } + else if (direction.X > a) + { + movementDirection = MovementDirection.NO; + } + else + { + movementDirection = MovementDirection.N; + } + } + return movementDirection; + } + /// + /// Save the movement data to a MovementData object. + /// + /// the MovementData object with the current status + public MovementData SaveData() + { + var data = new MovementData(); + data.IsMoving = IsMoving; + if (IsMoving) + { + data.Path = mPath; + data.Step = mStep; + data.LastMovement = mLastMovement; + } + return data; + } + + /// + /// Restore the movement state from the given data. + /// + /// the state of the movement to restore + public void LoadData(MovementData movementData) + { + if (movementData == null) + return; + + IsMoving = movementData.IsMoving; + if (IsMoving) + { + mPath = movementData.Path; + mStep = movementData.Step; + mLastMovement = movementData.LastMovement; + } + } + } +} diff --git a/V3/Objects/Necromancer.cs b/V3/Objects/Necromancer.cs new file mode 100644 index 0000000..b13650d --- /dev/null +++ b/V3/Objects/Necromancer.cs @@ -0,0 +1,61 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// A class for the player character: The Necromancer. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class Necromancer : AbstractCreature + { + public override string Name { get; protected set; } = "Vagram der Grausame"; + public override int Life { get; protected set; } = 500; + public override int MaxLife { get; protected set; } = 500; + public override int Speed { get; } = 12; + public override int Attack { get; protected set; } = 0; + public override int AttackRadius { get; protected set; } = 500; + public override int SightRadius { get; protected set; } = 0; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(1); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new NecromancerSprite(), new StaffSprite()}; + protected override IMovable MovementScheme { get; } = new CountStepsMovement(); + protected override CreatureType Type { get; } = CreatureType.Necromancer; + public override Faction Faction { get; } = Faction.Undead; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + public float WalkedPixels => ((CountStepsMovement) MovementScheme).WalkedPixels; + + public Necromancer(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + public void ChangeSex() + { + ISpriteCreature sprite0; + ISpriteCreature sprite1; + if (Sprite[0] is NecromancerSprite) + { + sprite0 = new NecromancerFemaleSprite(); + sprite1 = new StaffFemaleSprite(); + } + else + { + sprite0 = new NecromancerSprite(); + sprite1 = new StaffSprite(); + } + + ChangeEquipment(EquipmentType.Body, sprite0); + if (Sprite.Length >= 2 && Sprite[(int) EquipmentType.Head] != null) + { + ChangeEquipment(EquipmentType.Head, sprite1); + } + } + } +} diff --git a/V3/Objects/ObjectsManager.cs b/V3/Objects/ObjectsManager.cs new file mode 100644 index 0000000..e3ef568 --- /dev/null +++ b/V3/Objects/ObjectsManager.cs @@ -0,0 +1,314 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Camera; +using V3.Effects; +using V3.Map; + +namespace V3.Objects +{ + /// + /// Objects manager for all game objects, be is creatures or buildings or even simple landscape objects. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public class ObjectsManager : IObjectsManager + { + private List> mCreaturesByFactions; + private List mCreatureList; + private List mAddToSelectables; + private Quadtree mTextureQuadtree; + private Quadtree mInteractableQuadtree; + private readonly ContentManager mContentManager; + private readonly CreatureFactory mCreatureFactory; + private readonly IEffectsManager mEffectsManager; + private Rectangle mMapRectangle; + private List mAreas; + private readonly UpdatesPerSecond mFewerUpdates = new UpdatesPerSecond(15); + private readonly UpdatesPerSecond mEffectsCounter = new UpdatesPerSecond(0.2); + + public List AddToSelectables => mAddToSelectables; + public List CreatureList => mCreatureList; + public List UndeadCreatures => mCreaturesByFactions[(int) Faction.Undead]; + //public List KingdromCreatures => mCreaturesByFactions[(int) Faction.Kingdom]; + //public List PlebCreatures => mCreaturesByFactions[(int) Faction.Plebs]; + public ICreature PlayerCharacter { get; private set; } + public ICreature Boss { get; private set; } + public ICreature Prince { get; private set; } + public Castle Castle { get; private set; } + + public ObjectsManager(ContentManager contentManager, CreatureFactory creatureFactory, + IEffectsManager effectsManager) + { + mContentManager = contentManager; + mCreatureFactory = creatureFactory; + mEffectsManager = effectsManager; + } + + public void Initialize(IMapManager mapManager) + { + Clear(); + mAddToSelectables = new List(); + mCreatureList = new List(); + mCreaturesByFactions = new List>(); + // Make three lists because we have three factions. + for (int i = 0; i < 3; i++) + { + mCreaturesByFactions.Add(new List()); + } + // Gets the initial values for the Quad Tree from the current map. + mInteractableQuadtree = new Quadtree(mapManager.SizeInPixel + new Point(128, 128)); + mTextureQuadtree = new Quadtree(mapManager.SizeInPixel + new Point(128, 128)); + mInteractableQuadtree.LoadContent(mContentManager); + mTextureQuadtree.LoadContent(mContentManager); + + // Import map objects for drawing. + ImportMapObjects(mapManager.GetObjects()); + + // Save Map size in ObjectsManager. + mMapRectangle = new Rectangle(new Point(0), mapManager.SizeInPixel); + + mAreas = mapManager.Areas; + } + + public void Clear() + { + CreatureList?.Clear(); + mCreaturesByFactions?.Clear(); + for (int i = 0; i < 3; i++) + { + mCreaturesByFactions?.Add(new List()); + } + PlayerCharacter = null; + Boss = null; + Prince = null; + Castle = null; + mInteractableQuadtree?.Clear(); + mTextureQuadtree?.Clear(); + } + + public void CreatePlayerCharacter(Necromancer necromancer) + { + PlayerCharacter = necromancer; + AddCreature(necromancer); + } + + public void CreateBoss(ICreature boss) + { + Boss = boss; + AddCreature(boss); + } + + public void CreatePrince(ICreature prince) + { + Prince = prince; + AddCreature(prince); + } + + public void CreateCreature(ICreature creature) + { + AddCreature(creature); + } + + public void RemoveCreature(ICreature creature) + { + mCreatureList.Remove(creature); + mCreaturesByFactions[(int) creature.Faction].Remove(creature); + mInteractableQuadtree.RemoveItem(creature); + } + + public void Draw(SpriteBatch spriteBatch, ICamera camera) + { + var objectsToDraw = mInteractableQuadtree.GetObjectsInRectangle(camera.ScreenRectangle); + var texturesToDraw = mTextureQuadtree.GetObjectsInRectangle(camera.ScreenRectangle); + IEnumerable ordered = from obj in objectsToDraw.Concat(texturesToDraw) orderby obj.Position.Y select obj; + foreach (var obj in ordered) + { + obj.Draw(spriteBatch); + } + } + + public void DrawQuadtree(SpriteBatch spriteBatch) + { + mInteractableQuadtree.Draw(spriteBatch); + mTextureQuadtree.Draw(spriteBatch); + } + + public void Update(GameTime gameTime, bool rightButtonPressed, Vector2 rightButtonPosition, ICamera camera) + { + foreach (var creature in mCreatureList) + { + if (creature.GetSelf() == null) continue; + creature.Update(gameTime, PlayerCharacter, rightButtonPressed, rightButtonPosition, mInteractableQuadtree, camera); + + + // Create a boss if castle is down + if (creature.IsAttackingBuilding != null && creature.IsAttackingBuilding.Name == "Burg") + { + if (creature.IsAttackingBuilding.Robustness <= 50 && Boss == null) + { + var king = mCreatureFactory.CreateKing(new Vector2(creature.IsAttackingBuilding.Position.X - 300, creature.IsAttackingBuilding.Position.Y + 130), MovementDirection.S); // + var knight1 = mCreatureFactory.CreateKnight(new Vector2(creature.IsAttackingBuilding.Position.X - 320, creature.IsAttackingBuilding.Position.Y + 110), MovementDirection.S); // + var knight2 = mCreatureFactory.CreateKnight(new Vector2(creature.IsAttackingBuilding.Position.X - 280, creature.IsAttackingBuilding.Position.Y + 150), MovementDirection.S); // + CreateBoss(king); + AddCreature(knight1); + AddCreature(knight2); + break; + } + //break; + } + // Checks if the creature moved out of the map and resets its position as appropriate. + if (!mMapRectangle.Contains(creature.Position)) + { + creature.ResetPosition(); + } + } + if (mFewerUpdates.IsItTime(gameTime)) + { + mInteractableQuadtree.Update(); + } + + #region Boss Special Attack + // Play some cool effects when boss is spawned so he looks cooler. + // Added a small special attack which does at bit AoE damage. + if (mEffectsCounter.IsItTime(gameTime)) + { + if (Boss != null && camera.ScreenRectangle.Contains(Boss.Position)) + { + mEffectsManager.PlayOnce(new Quake(), Boss.Position.ToPoint(), new Point(256, 128)); + var aoeRadius = new Rectangle(Boss.Position.ToPoint() - new Point(128), new Point(256)); + var effectedCreatures = mInteractableQuadtree.GetObjectsInRectangle(aoeRadius); + foreach (var obj in effectedCreatures) + { + var creature = obj as ICreature; + if (creature != null && creature.Faction == Faction.Undead && creature.BoundaryRectangle.Intersects(aoeRadius)) + { + creature.TakeDamage(10); + } + } + } + } + #endregion + + #region Necromancer stuff + if (PlayerCharacter.IsSelected && rightButtonPressed) + { + var objectsUnderMouse = + mInteractableQuadtree.GetObjectsInRectangle(new Rectangle(rightButtonPosition.ToPoint(), new Point(1, 1))); + foreach (var obj in objectsUnderMouse) + { + var creature = obj as ICreature; + if (creature == null || !creature.SelectionRectangle.Contains(rightButtonPosition) || !creature.IsDead || creature.Faction == Faction.Undead) continue; + if (Vector2.Distance(PlayerCharacter.Position, creature.Position) > PlayerCharacter.AttackRadius) continue; + RemoveCreature(creature); + if (creature is KingsGuard || creature is King || creature is Prince) + { + CreateCreature(mCreatureFactory.CreateSkeletonElite(creature.Position, creature.MovementDirection)); + } + else + { + CreateCreature(mCreatureFactory.CreateZombie(creature.Position, creature.MovementDirection)); + } + PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new BloodBang(), creature.Position.ToPoint(), new Point(128)); + break; + } + } + #endregion Necromancer stuff + + #region SkeletonRider + + var recMouse = new Rectangle(rightButtonPosition.ToPoint(), new Point(1, 1)); + foreach (var creature in UndeadCreatures) + { + Skeleton skeleton = creature as Skeleton; + if (skeleton != null) + { + if(skeleton.IsSelected && rightButtonPressed) + { + var atMousPosition = mInteractableQuadtree.GetObjectsInRectangle(recMouse); + foreach (var wannabehorse in atMousPosition) + { + var horse = wannabehorse as SkeletonHorse; + if (horse != null && Vector2.Distance(skeleton.Position, horse.Position) < 32) + { + horse.Mount(skeleton); + horse.IsSelected = true; + mAddToSelectables.Add(horse); + } + } + } + } + } + #endregion SkeletonRider + } + + private void AddCreature(ICreature creature) + { + if (!mMapRectangle.Contains(creature.BoundaryRectangle)) return; + mCreatureList.Add(creature); + mCreaturesByFactions[(int) creature.Faction].Add(creature); + mInteractableQuadtree.Insert(creature); + } + + public void ImportMapObjects(List textureObjects) + { + foreach (var obj in textureObjects) + { + if (obj is IBuilding) + { + mInteractableQuadtree.Insert(obj); + if (obj is Castle) + Castle = (Castle) obj; + } + else + { + mTextureQuadtree.Insert(obj); + } + } + } + + public List GetObjectsInRectangle(Rectangle rectangle) + { + return mInteractableQuadtree.GetObjectsInRectangle(rectangle); + } + + public List GetCreaturesInEllipse(Ellipse ellipse) + { + var setToReturn = new List(); + foreach (var obj in mInteractableQuadtree.GetObjectsInRectangle(ellipse.BoundaryRectangle)) + { + ICreature creature = obj as ICreature; + if (creature != null && ellipse.Contains(creature.Position)) + { + setToReturn.Add(creature); + } + } + return setToReturn; + } + + public void ExposeTheLiving() + { + foreach (var creature in mCreatureList) + { + if (creature.Faction == Faction.Plebs) + { + (creature as MalePeasant)?.RemoveArmor(); + (creature as FemalePeasant)?.RemoveArmor(); + } + else if (creature.Faction == Faction.Kingdom) + { + (creature as Knight)?.RemoveArmor(); + (creature as KingsGuard)?.RemoveArmor(); + } + } + } + + public bool InGraveyardArea(ICreature creature) + { + return mAreas.Where(area => area.Type == AreaType.Graveyard).Select(area => area.Contains(creature)).Any(contains => contains); + } + } +} diff --git a/V3/Objects/Prince.cs b/V3/Objects/Prince.cs new file mode 100644 index 0000000..b806f41 --- /dev/null +++ b/V3/Objects/Prince.cs @@ -0,0 +1,33 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class Prince : AbstractCreature + { + public override string Name { get; protected set; } = "Prinz Erhard"; + public override int Life { get; protected set; } = 6000; + public override int MaxLife { get; protected set; } = 6000; + public override int Speed { get; } = 10; + public override int Attack { get; protected set; } = 35; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 500; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.5); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = { new PrinceSprite() }; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.Prince; + public override Faction Faction { get; } = Faction.Kingdom; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public Prince(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + } +} diff --git a/V3/Objects/Selection.cs b/V3/Objects/Selection.cs new file mode 100644 index 0000000..4ec7ccc --- /dev/null +++ b/V3/Objects/Selection.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Data; +using V3.Effects; + +namespace V3.Objects +{ + /// + /// Class for selecting creatures, holding the selection and drawing the selection rectangle on the screen. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class Selection + { + private IObjectsManager mObjectsManager; + private IEffectsManager mEffectsManager; + private readonly Color mColor = Color.Black; + private Texture2D mTexture; + public List SelectedCreatures { get; private set; } = new List(); + private List TransformList { get; } = new List(); + private readonly CreatureFactory mCreatureFactory; + private int mDeadBodies; + private int mExplosionDeaths; + private Ellipse NecroArea { get; set; } + public Rectangle LastSelection { get; private set; } + private SoundEffect mSoundEffect; + private SoundEffectInstance mSoundEffectInstance; + private IOptionsManager mOptionsManager; + private AchievementsAndStatistics mAchievementsAndStatistics; + + public Selection(ContentManager contentManager, CreatureFactory creatureFactory, IObjectsManager objectsManager, + IEffectsManager effectsManager, IOptionsManager optionsmanager, AchievementsAndStatistics achievementsAndStatistics) + { + mCreatureFactory = creatureFactory; + mObjectsManager = objectsManager; + mEffectsManager = effectsManager; + mOptionsManager = optionsmanager; + mAchievementsAndStatistics = achievementsAndStatistics; + LoadContent(contentManager); + } + + private void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Sprites/WhiteRectangle"); + mSoundEffect = contentManager.Load("Sounds/zonk2"); + mSoundEffectInstance = mSoundEffect.CreateInstance(); + } + + /// + /// Select all objects in the area of the rectangle between origin and destination. + /// + /// Position in pixels where the mouse button was pressed down. + /// Position in pixels where the mouse button was released. + public void Select(Point origin, Point destination) + { + // Clean last selection + SelectedCreatures.ForEach(e => e.IsSelected=false); + SelectedCreatures.Clear(); + + // New selection + int x, y, width, height; + if (origin.X > destination.X) + { + x = destination.X; + width = origin.X - destination.X; + } + else + { + x = origin.X; + width = destination.X - origin.X; + } + if (origin.Y > destination.Y) + { + y = destination.Y; + height = origin.Y - destination.Y; + } + else + { + y = origin.Y; + height = destination.Y - origin.Y; + } + + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int)necroPos.Position.X, (int)necroPos.Position.Y), 1280, 640); + + // List for all objects in the current selection + LastSelection = new Rectangle(x, y, width, height); + var selectedObjects = mObjectsManager.GetObjectsInRectangle(LastSelection); + + // Lists to seperate undead from enemy creatures + var enemyCreatures = new List(); + var undeadCreatures = new List(); + + foreach (var obj in selectedObjects) + { + var creature = obj as ICreature; + // Give priority when selecting undead creatures. + if (creature != null && !creature.IsDead && LastSelection.Intersects(creature.SelectionRectangle) && NecroArea.Contains(creature.Position)) + { + if (creature.Faction != Faction.Undead) + { + enemyCreatures.Add(creature); + } + else + { + undeadCreatures.Add(creature); + } + } + } + SelectedCreatures = undeadCreatures.Count == 0 ? enemyCreatures : undeadCreatures; + + // Make all selectable creatures selected + foreach (var selectedCreature in SelectedCreatures) + { + selectedCreature.IsSelected = true; + } + } + + /// + /// Draw the selection rectangle on the screen. + /// + /// Sprite batch used. + /// Position in pixels where the mouse button was pressed down. + /// Position in pixels where the mouse button was released. + public void Draw(SpriteBatch spriteBatch, Point origin, Point destination) + { + if (origin.X > destination.X) + { + spriteBatch.Draw(mTexture, new Rectangle(destination.X, origin.Y, origin.X - destination.X, 2), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, destination.Y, origin.X - destination.X, 2), mColor); + } + else + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, origin.Y, destination.X - origin.X, 2), mColor); + spriteBatch.Draw(mTexture, new Rectangle(origin.X, destination.Y, destination.X - origin.X, 2), mColor); + } + if (origin.Y > destination.Y) + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, destination.Y, 2, origin.Y - destination.Y), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, destination.Y, 2, origin.Y - destination.Y), mColor); + } + else + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, origin.Y, 2, destination.Y - origin.Y), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, origin.Y, 2, destination.Y - origin.Y), mColor); + } + } + + /// + /// Press 1 to trigger the specialattack of the meatball + /// All non undead creatures at the distance of 200 pixels take damage + /// After the attack the meatball disappears and three zombies will be created + /// + public void Specialattack() + { + foreach (var creature in SelectedCreatures) + { + var meatball = creature as Meatball; + if (meatball != null) + { + // Creates radius for meatballs explosion + var explosionRadius = new Rectangle((int)meatball.Position.X - 200, (int)meatball.Position.Y - 200, 400, 400); + var objectsInMeatballArea = mObjectsManager.GetObjectsInRectangle(explosionRadius); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new Explosion(), meatball.Position.ToPoint(), explosionRadius.Size * new Point(3, 2)); + + // All attackable creatures take damage (own undead creatures won't take damage) + foreach (var attackable in objectsInMeatballArea) + { + var toAttack = attackable as ICreature; + if (toAttack != null && toAttack.Faction != Faction.Undead) + { + toAttack.TakeDamage(meatball.Attack); + if (toAttack.IsDead) + mExplosionDeaths += 1; + } + } + + if (mExplosionDeaths >= 10) + mAchievementsAndStatistics.mKaboom = true; + mExplosionDeaths = 0; + + // The new zombies after explosion + var zombie1 = mCreatureFactory.CreateZombie(meatball.Position, meatball.MovementDirection); + var zombie2 = mCreatureFactory.CreateZombie(new Vector2(meatball.Position.X + 50, meatball.Position.Y + 50), meatball.MovementDirection); + var zombie3 = mCreatureFactory.CreateZombie(new Vector2(meatball.Position.X - 50, meatball.Position.Y - 50), meatball.MovementDirection); + + // Makes zombies be selected after explosion + zombie1.IsSelected = true; + zombie2.IsSelected = true; + zombie3.IsSelected = true; + meatball.IsSelected = false; + SelectedCreatures.Add(zombie1); + SelectedCreatures.Add(zombie2); + SelectedCreatures.Add(zombie3); + SelectedCreatures.Remove(meatball); + + // Remove meatball from game + mObjectsManager.RemoveCreature(meatball); + + // Add zombies to game + mObjectsManager.CreateCreature(zombie1); + mObjectsManager.CreateCreature(zombie2); + mObjectsManager.CreateCreature(zombie3); + + // For every zombie the necromancer gets healed + var heal = mObjectsManager.PlayerCharacter.Life * 0.12; + mObjectsManager.PlayerCharacter.Heal((int)heal); + + break; + } + } + } + + /// + /// Press 2 to create zombies from dead bodies + /// At least one dead body should be in necromancers area + /// + public void TransformZombie() + { + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int) necroPos.Position.X, (int) necroPos.Position.Y), 1280, 640); + + // Get all creatures in necromancers area + var necroArea = mObjectsManager.GetCreaturesInEllipse(NecroArea); + + // Every dead body in necromancer area will be transformed to an zombie + // The prince will be transformed to an elite zombie + foreach (var creature in necroArea) + { + if (creature.Faction == Faction.Plebs || creature.Faction == Faction.Kingdom) + { + if (creature.IsDead) + { + ICreature zombie; + if (creature is KingsGuard || creature is King || creature is Prince) + zombie = mCreatureFactory.CreateSkeletonElite(creature.Position, creature.MovementDirection); + else + zombie = mCreatureFactory.CreateZombie(creature.Position, creature.MovementDirection); + + // Add zombie to game + mObjectsManager.CreateCreature(zombie); + + // Remove dead body from game + mObjectsManager.RemoveCreature(creature); + + // Play sounds and effects + mEffectsManager.PlayOnce(new BloodBang(), zombie.Position.ToPoint(), new Point(128)); + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, + TimeSpan.FromSeconds(0.5d)); + + // The number of dead bodies + mDeadBodies++; + + // For every zombie the necromancer gets healed + var heal = mObjectsManager.PlayerCharacter.Life * 0.04; + mObjectsManager.PlayerCharacter.Heal((int)heal); + } + } + } + + // Counts dead bodies in necromancers area and undead creatures + var set = mDeadBodies + mObjectsManager.UndeadCreatures.Count; + if (mObjectsManager.InGraveyardArea(mObjectsManager.PlayerCharacter) && set < 6) + { + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + for (int i = 1; i <= 6 - set; i++) + { + var positionX = mObjectsManager.PlayerCharacter.Position.X + (float)Math.Sin(i) * 75; + var positionY = mObjectsManager.PlayerCharacter.Position.Y + (float)Math.Cos(i) * 75; + var zombie = mCreatureFactory.CreateZombie(new Vector2(positionX, positionY), mObjectsManager.PlayerCharacter.MovementDirection); + mObjectsManager.CreateCreature(zombie); + zombie.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(1)); + } + } + mDeadBodies = 0; + } + + /// + /// Press 3 to create a meatball in exchange for five zombie + /// At least five zombies should be selected + /// + public void TransformMeatball() + { + // The cost for this transformation + var cost = mObjectsManager.PlayerCharacter.MaxLife * 0.12; + + // Transform only when necromancer life minus the transformations cost is not lower than 1 + if (mObjectsManager.PlayerCharacter.Life - (int)cost >= 1) + { + // Puts all zombies in a seperate list called TransformList + foreach (var creature in SelectedCreatures) + { + var zombie = creature as Zombie; + if (zombie != null && TransformList.Count < 5) + { + TransformList.Add(zombie); + } + } + + // Creates the meatball and makes him selected + if (TransformList.Count >= 5) + { + // Delete zombies from game and SelectedCratures + foreach (var zombie in TransformList) + { + SelectedCreatures.Remove(zombie); + mObjectsManager.RemoveCreature(zombie); + } + + // Add meatball to game + // Position will be randomly chosen from one of the zombies + var randomNumber = new Random(); + var positionMeatball = randomNumber.Next(5); + var meatball = mCreatureFactory.CreateMeatball(TransformList[positionMeatball].Position, + TransformList[positionMeatball].MovementDirection); + meatball.IsSelected = true; + SelectedCreatures.Add(meatball); + mObjectsManager.CreateCreature(meatball); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new BloodExplosion(), meatball.Position.ToPoint(), new Point(256)); + + // Necromancer takes damage + mObjectsManager.PlayerCharacter.TakeDamage((int)cost); + } + TransformList.Clear(); + } + else + { + // Play sound when transformation not possible + mSoundEffectInstance.Volume = mOptionsManager.Options.GetEffectiveVolume(); + mSoundEffectInstance.Play(); + } + } + + + /// + /// Press 4 to create an skeleton in exchange for an zombie + /// At least one zombie should be selected + /// + public void TransformSkeleton() + { + // Iterates through SelectedCreatures and takes the first zombie + foreach (var creature in SelectedCreatures) + { + var zombie = creature as Zombie; + if (zombie != null) + { + // Delete zombie + SelectedCreatures.Remove(zombie); + mObjectsManager.RemoveCreature(zombie); + + // Add skeleton + var skeleton = mCreatureFactory.CreateSkeleton(zombie.Position, zombie.MovementDirection); + skeleton.IsSelected = true; + SelectedCreatures.Add(skeleton); + mObjectsManager.CreateCreature(skeleton); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new BloodFountain(), zombie.Position.ToPoint() - new Point(0, 64), new Point(128)); + + break; + } + } + } + + /// + /// Press 5 to create an skeletonhorse in exchange for three skeletons + /// At least three skeletons should be selected + /// + public void TransformSkeletonHorse() + { + // The cost for this transformation + var cost = mObjectsManager.PlayerCharacter.MaxLife * 0.06; + + // Transform only when necromancer life minus the transformations cost is not lower than 1 + if (mObjectsManager.PlayerCharacter.Life - (int)cost >= 1) + { + + // Puts all skeletons in a seperate list called TransformList + foreach (var creature in SelectedCreatures) + { + var skeleton = creature as Skeleton; + if (skeleton != null && TransformList.Count < 3) + { + TransformList.Add(skeleton); + } + } + + // Creates the skeletonhorse and makes him selected + if (TransformList.Count >= 3) + { + // Delete zombies from game and SelectedCratures + foreach (var skeleton in TransformList) + { + SelectedCreatures.Remove(skeleton); + mObjectsManager.RemoveCreature(skeleton); + } + + // Add skeletonhorse to game + // Position will be randomly chosen from one of the skeletons + var randomNumber = new Random(); + var positionHorse = randomNumber.Next(3); + var skeletonHorse = mCreatureFactory.CreateSkeletonHorse(TransformList[positionHorse].Position, + TransformList[positionHorse].MovementDirection); + skeletonHorse.IsSelected = true; + SelectedCreatures.Add(skeletonHorse); + mObjectsManager.CreateCreature(skeletonHorse); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new HorseEffect(), skeletonHorse.Position.ToPoint() - new Point(0, 16), new Point(128)); + + + // Necromancer takes damage + mObjectsManager.PlayerCharacter.TakeDamage((int)cost); + } + TransformList.Clear(); + } + else + { + // Play sound when transformation not possible + mSoundEffectInstance.Volume = mOptionsManager.Options.GetEffectiveVolume(); + mSoundEffectInstance.Play(); + } + } + + /// + /// If creature leaves area og the necromancer, he gets disselected + /// + public void UpdateSelection() + { + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int)necroPos.Position.X, (int)necroPos.Position.Y), 1280, 640); + + foreach (var creature in SelectedCreatures) + { + if (!NecroArea.Contains(creature.Position) || creature.IsDead) + creature.IsSelected = false; + } + + if (mObjectsManager.AddToSelectables.Count > 0) + { + SelectedCreatures.Add(mObjectsManager.AddToSelectables[0]); + mObjectsManager.AddToSelectables.Clear(); + } + } + + /// + /// Give movement command to selected creatures. + /// + /// Desired destination in pixels. + public void Move(Vector2 destination) + { + if (SelectedCreatures.Count == 0) return; + var centreCreature = SelectedCreatures[0]; + // You can not move enemy creatures. + if (centreCreature.Faction != Faction.Undead) return; + centreCreature.Move(destination); + + for (int i = 1; i < SelectedCreatures.Count; i++) + { + Vector2 flockDestination = destination; + Vector2 distance = centreCreature.Position - SelectedCreatures[i].Position; + distance.Normalize(); + distance *= 70; + flockDestination -= distance; + SelectedCreatures[i].Move(flockDestination); + } + } + } +} diff --git a/V3/Objects/Skeleton.cs b/V3/Objects/Skeleton.cs new file mode 100644 index 0000000..58eda62 --- /dev/null +++ b/V3/Objects/Skeleton.cs @@ -0,0 +1,65 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// A skeleton controlled by the necromancer. + /// + public class Skeleton : AbstractCreature + { + /// + /// If the skeleton is mounted, it is not updated and drawn anymore because + /// instead the horse sprite is moved. + /// + public bool Mounted { private get; set; } + + public override string Name { get; protected set; } = "Skelett"; + public override int Life { get; protected set; } = 100; + public override int MaxLife { get; protected set; } = 100; + public override int Speed { get; } = 10; + public override int Attack { get; protected set; } = 10; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 150; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.5); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new SkeletonSprite()}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.Skeleton; + public override Faction Faction { get; } = Faction.Undead; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + // ReSharper disable once MemberCanBeProtected.Global + public Skeleton(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager,achievementsAndStatistics) + { + } + + public override IGameObject GetSelf() + { + return Mounted ? null : base.GetSelf(); + } + + public override CreatureData SaveData() + { + var data = base.SaveData(); + data.Mounted = Mounted; + return data; + } + + public override void LoadData(CreatureData data) + { + base.LoadData(data); + Mounted = data.Mounted; + + if (IsUpgraded) + ChangeEquipment(EquipmentType.Body, new SkeletonArcherSprite()); + } + } +} diff --git a/V3/Objects/SkeletonElite.cs b/V3/Objects/SkeletonElite.cs new file mode 100644 index 0000000..ac3c6c4 --- /dev/null +++ b/V3/Objects/SkeletonElite.cs @@ -0,0 +1,19 @@ +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + public sealed class SkeletonElite : Skeleton + { + public override int Life { get; protected set; } = 200; + public override int MaxLife { get; protected set; } = 200; + public override int Attack { get; protected set; } = 30; + protected override ISpriteCreature[] Sprite { get; } = { new SkeletonEliteSprite() }; + + public SkeletonElite(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + } +} \ No newline at end of file diff --git a/V3/Objects/SkeletonHorse.cs b/V3/Objects/SkeletonHorse.cs new file mode 100644 index 0000000..6cd441d --- /dev/null +++ b/V3/Objects/SkeletonHorse.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + public sealed class SkeletonHorse : AbstractCreature + { + public SkeletonHorse(ContentManager contentManager, Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) : base(contentManager, pathfinder, optionsManager, achievementsAndStatistics) + { + } + + private Skeleton mSkeleton; + + protected override ISpriteCreature[] Sprite { get; } = {new SkeletonHorseSprite()}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.SkeletonHorse; + public override string Name { get; protected set; } = "Totenpferd"; + public override int Life { get; protected set; } = 150; + public override int MaxLife { get; protected set; } = 150; + public override int Speed { get; } = 20; + public override int Attack { get; protected set; } + public override int AttackRadius { get; protected set; } + public override int SightRadius { get; protected set; } + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(0.5); + public override TimeSpan Recovery { get; set; } + public override Faction Faction { get; } = Faction.Undead; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + protected override Point CreatureSize { get; } = new Point(36); + protected override Point BoundaryShift { get; } = new Point(-18, -24); + + /// + /// A skeleton mounts a horse, becoming a skeleton rider. + /// + /// The skeleton which mounts the horse. + public void Mount(Skeleton skeleton) + { + if (IsDead || skeleton.IsDead || mSkeleton != null) return; + skeleton.Mounted = true; + mSkeleton = skeleton; + ChangeEquipment(EquipmentType.Body, new SkeletonRiderSprite()); + Attack = skeleton.Attack; + AttackRadius = skeleton.AttackRadius * 2; + // Sight radius is higher because skeleton is mounted. + SightRadius = skeleton.SightRadius * 2; + Name = "Skelettreiter"; + } + + protected override void Die() + { + if (mSkeleton != null) + { + mSkeleton.Position = Position; + mSkeleton.Mounted = false; + mSkeleton = null; + ChangeEquipment(EquipmentType.Body, new SkeletonHorseSprite()); + } + base.Die(); + } + + public override CreatureData SaveData() + { + var data = base.SaveData(); + if (mSkeleton != null) + data.SkeletonId = mSkeleton.Id; + return data; + } + + public override void LoadReferences(CreatureData data, Dictionary creatures) + { + base.LoadReferences(data, creatures); + if (creatures.ContainsKey(data.SkeletonId)) + { + var creature = creatures[data.SkeletonId]; + if (creature is Skeleton) + Mount((Skeleton) creature); + } + } + } +} diff --git a/V3/Objects/Sprite/AbstractSpriteCreature.cs b/V3/Objects/Sprite/AbstractSpriteCreature.cs new file mode 100644 index 0000000..bde139e --- /dev/null +++ b/V3/Objects/Sprite/AbstractSpriteCreature.cs @@ -0,0 +1,201 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects.Sprite +{ + public abstract class AbstractSpriteCreature : ISpriteCreature + { + // How many frames are there for each animation type? + protected virtual int IdleFrames { get; } = 4; + protected virtual int MovingFrames { get; } = 8; + protected virtual int AttackingFrames { get; } = 4; + protected virtual int DyingFrames { get; } = 6; + protected virtual int SpecialFrames { get; } = 4; + + /// The row of the specific textures in the texture file. + protected virtual int IdleTextureIndex { get; } = 0; + protected virtual int MovingTextureIndex { get; } = 4; + protected virtual int AttackingTextureIndex { get; } = 12; + protected virtual int DyingTextureIndex { get; } = 18; + protected virtual int SpecialTextureIndex { get; } = 24; + + + // Specify the size of a single animation frame in pixel. + private const int SpriteWidth = 128; + private const int SpriteHeight = 128; + private readonly Point mSpriteShift = new Point(-SpriteWidth / 2, -SpriteHeight * 3 / 4); + private readonly Point mSpriteSize = new Point(SpriteWidth, SpriteHeight); + + private double mTimeSinceUpdate; + private Texture2D mTexture; + // How much time until animation frame is changed (in milliseconds). + private const int UpdatesPerMSec = 125; // 8 FPS + private MovementState mLastMovementState = MovementState.Idle; + private MovementState mCurrentMovementState = MovementState.Idle; + private int mMaxAnimationSteps; + private int mMovementStateRow; + private bool mIdleBackwardsLoop; + private int mAnimationState; + + // Fields for PlayOnce method. + private bool mPriorityAnimation; + private UpdatesPerSecond mUpS; + + protected abstract string TextureFile { get; } + + /// + /// Loads the texture file and prepares animations. + /// + /// + public void Load(ContentManager contentManager) + { + mTexture = contentManager.Load("Sprites/" + TextureFile); + mMaxAnimationSteps = IdleFrames; + } + + /// + /// Draws the sprite on the screen. + /// + /// Sprite batch used for drawing. + /// Position on the screen where sprite is drawn to. + /// What moveset will be used? (Moving, Attacking...) + /// Where does the sprite face? + public void Draw(SpriteBatch spriteBatch, Vector2 position, MovementState movementState, MovementDirection movementDirection) + { + mCurrentMovementState = movementState; + Point sourceLocation = new Point((mMovementStateRow + mAnimationState) * SpriteWidth, + (int) movementDirection * SpriteHeight); + Rectangle sourceRectangle = new Rectangle(sourceLocation, mSpriteSize); + spriteBatch.Draw(mTexture, position + new Vector2(mSpriteShift.X, mSpriteShift.Y), sourceRectangle, Color.White); + } + + public void DrawStatic(SpriteBatch spriteBatch, Point position, MovementState movementState, MovementDirection movementDirection) + { + Point sourceLocation = new Point((int)movementState * SpriteWidth, (int)movementDirection * SpriteHeight); + Rectangle destinationRectangle = new Rectangle(position + mSpriteShift, mSpriteSize); + Rectangle sourceRectangle = new Rectangle(sourceLocation, mSpriteSize); + spriteBatch.Draw(mTexture, destinationRectangle, sourceRectangle, Color.White); + } + + /// + /// Change the sprite to show an animation. + /// + /// Elapsed game time is used for calculating FPS. + public void PlayAnimation(GameTime gameTime) + { + // Playing a single animation cycle just once with higher priority. + if (mPriorityAnimation) + { + if (mAnimationState < mMaxAnimationSteps - 1) + { + if (mUpS.IsItTime(gameTime)) + { + mAnimationState++; + } + return; + } + mAnimationState = 0; + mCurrentMovementState = mLastMovementState; + SelectFrames(mCurrentMovementState); + mPriorityAnimation = false; + return; + } + + // Change texture for showing animations according to elapsed game time. + mTimeSinceUpdate += gameTime.ElapsedGameTime.TotalMilliseconds; + if (mTimeSinceUpdate < UpdatesPerMSec) + { + return; + } + mTimeSinceUpdate = 0; + + // Check which specific animation sprites need to be used. + // Only check if movement state is changed. + if (mCurrentMovementState != mLastMovementState) + { + SelectFrames(mCurrentMovementState); + mAnimationState = 0; + mLastMovementState = mCurrentMovementState; + } + + // Idle animation is looped back and forth. + if (mIdleBackwardsLoop) + { + mAnimationState--; + if (mAnimationState <= 0) + { + mIdleBackwardsLoop = false; + } + return; + } + + if (mAnimationState < mMaxAnimationSteps - 1) + { + mAnimationState++; + } + else + { + if (mLastMovementState == MovementState.Idle) + { + mIdleBackwardsLoop = true; + mAnimationState--; + } + else if (mLastMovementState == MovementState.Dying) + { + } + else + { + mAnimationState = 0; + } + } + } + + private void SelectFrames(MovementState currentMovementState) + { + switch (currentMovementState) + { + case MovementState.Idle: + mMaxAnimationSteps = IdleFrames; + mMovementStateRow = IdleTextureIndex; + mIdleBackwardsLoop = false; + break; + case MovementState.Moving: + mMaxAnimationSteps = MovingFrames; + mMovementStateRow = MovingTextureIndex; + break; + case MovementState.Attacking: + mMaxAnimationSteps = AttackingFrames; + mMovementStateRow = AttackingTextureIndex; + break; + case MovementState.Dying: + mMaxAnimationSteps = DyingFrames; + mMovementStateRow = DyingTextureIndex; + break; + case MovementState.Special: + mMaxAnimationSteps = SpecialFrames; + mMovementStateRow = SpecialTextureIndex; + break; + default: + mMaxAnimationSteps = 1; // No Animation if default case is reached. + break; + } + } + + /// + /// Plays the specified animation fully, but only once. + /// + /// For which movement state the animation should be played. + /// How long (or how slow) should the animation be? + public void PlayOnce(MovementState animation, TimeSpan duration) + { + mLastMovementState = mCurrentMovementState; + mCurrentMovementState = animation; + mPriorityAnimation = true; + SelectFrames(animation); + mAnimationState = 0; + mUpS = new UpdatesPerSecond(1d / (duration.TotalSeconds / mMaxAnimationSteps)); + } + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ArrowSprite.cs b/V3/Objects/Sprite/ArrowSprite.cs new file mode 100644 index 0000000..76e34b7 --- /dev/null +++ b/V3/Objects/Sprite/ArrowSprite.cs @@ -0,0 +1,42 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects.Sprite +{ + /// + /// A simple arrow from different directions without animations. + /// + public sealed class ArrowSprite : ISpriteCreature + { + private Texture2D mTexture; + private const int Size = 64; + + public void Load(ContentManager contentManager) + { + mTexture = contentManager.Load("Sprites/arrows"); + } + + public void Draw(SpriteBatch spriteBatch, Vector2 position, MovementState movementState, MovementDirection movementDirection) + { + spriteBatch.Draw(mTexture, position - new Vector2(Size / 2f), new Rectangle(0, Size * (int) movementDirection, Size, Size), Color.White); + } + + public void DrawStatic(SpriteBatch spriteBatch, + Point position, + MovementState movementState, + MovementDirection movementDirection) + { + Draw(spriteBatch, position.ToVector2(), movementState, movementDirection); + } + + public void PlayAnimation(GameTime gameTime) + { + } + + public void PlayOnce(MovementState animation, TimeSpan duration) + { + } + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/BucklerFemaleSprite.cs b/V3/Objects/Sprite/BucklerFemaleSprite.cs new file mode 100644 index 0000000..7d72869 --- /dev/null +++ b/V3/Objects/Sprite/BucklerFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class BucklerFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "buckler_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/BucklerSprite.cs b/V3/Objects/Sprite/BucklerSprite.cs new file mode 100644 index 0000000..c55ed81 --- /dev/null +++ b/V3/Objects/Sprite/BucklerSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class BucklerSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "buckler"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ChainFemaleSprite.cs b/V3/Objects/Sprite/ChainFemaleSprite.cs new file mode 100644 index 0000000..eddfe9d --- /dev/null +++ b/V3/Objects/Sprite/ChainFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ChainFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "chain_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ChainSprite.cs b/V3/Objects/Sprite/ChainSprite.cs new file mode 100644 index 0000000..33e7042 --- /dev/null +++ b/V3/Objects/Sprite/ChainSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ChainSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "chain"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ClothFemaleSprite.cs b/V3/Objects/Sprite/ClothFemaleSprite.cs new file mode 100644 index 0000000..3edaec1 --- /dev/null +++ b/V3/Objects/Sprite/ClothFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ClothFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "cloth_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ClothSprite.cs b/V3/Objects/Sprite/ClothSprite.cs new file mode 100644 index 0000000..b3aaff0 --- /dev/null +++ b/V3/Objects/Sprite/ClothSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ClothSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "cloth"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/EquipmentType.cs b/V3/Objects/Sprite/EquipmentType.cs new file mode 100644 index 0000000..611c35d --- /dev/null +++ b/V3/Objects/Sprite/EquipmentType.cs @@ -0,0 +1,10 @@ +namespace V3.Objects.Sprite +{ + /// + /// Different types of equipment slots. + /// + public enum EquipmentType + { + Body, Head, Weapon, Offhand + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadBaldSprite.cs b/V3/Objects/Sprite/HeadBaldSprite.cs new file mode 100644 index 0000000..7b01e16 --- /dev/null +++ b/V3/Objects/Sprite/HeadBaldSprite.cs @@ -0,0 +1,10 @@ +using System.Diagnostics.CodeAnalysis; + +namespace V3.Objects.Sprite +{ + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public sealed class HeadBaldSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_bald"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadChainFemaleSprite.cs b/V3/Objects/Sprite/HeadChainFemaleSprite.cs new file mode 100644 index 0000000..8d8ed90 --- /dev/null +++ b/V3/Objects/Sprite/HeadChainFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class HeadChainFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_chain_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadChainSprite.cs b/V3/Objects/Sprite/HeadChainSprite.cs new file mode 100644 index 0000000..31476f1 --- /dev/null +++ b/V3/Objects/Sprite/HeadChainSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class HeadChainSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_chain"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadFemaleSprite.cs b/V3/Objects/Sprite/HeadFemaleSprite.cs new file mode 100644 index 0000000..b8649aa --- /dev/null +++ b/V3/Objects/Sprite/HeadFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class HeadFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadPlateFemaleSprite.cs b/V3/Objects/Sprite/HeadPlateFemaleSprite.cs new file mode 100644 index 0000000..8ad7917 --- /dev/null +++ b/V3/Objects/Sprite/HeadPlateFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class HeadPlateFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_plate_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadPlateSprite.cs b/V3/Objects/Sprite/HeadPlateSprite.cs new file mode 100644 index 0000000..fa237b3 --- /dev/null +++ b/V3/Objects/Sprite/HeadPlateSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class HeadPlateSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head_plate"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/HeadSprite.cs b/V3/Objects/Sprite/HeadSprite.cs new file mode 100644 index 0000000..303bb8a --- /dev/null +++ b/V3/Objects/Sprite/HeadSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class HeadSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "head"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ISpriteCreature.cs b/V3/Objects/Sprite/ISpriteCreature.cs new file mode 100644 index 0000000..1339b2a --- /dev/null +++ b/V3/Objects/Sprite/ISpriteCreature.cs @@ -0,0 +1,53 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; + +namespace V3.Objects.Sprite +{ + /// + /// + /// + public interface ISpriteCreature + { + /// + /// Loads the texture file and prepares animations. + /// + /// Content manager used. + void Load(ContentManager contentManager); + + /// + /// Draws the sprite on the screen. + /// + /// Sprite batch used for drawing. + /// Position on the screen in pixels where the sprite should stand. + /// What moveset will be used? (Moving, Attacking...) + /// Where does the sprite face to? + void Draw(SpriteBatch spriteBatch, Vector2 position, MovementState movementState, MovementDirection movementDirection); + + /// + /// Draws a static image of the sprite. No animations. + /// + /// Sprite batch used for drawing. + /// Position of the sprite in pixels. (Where are the feet of the sprite placed. + /// What moveset will be used? (Moving, Attacking...) + /// Where does the sprite face to? + void DrawStatic(SpriteBatch spriteBatch, + Point position, + MovementState movementState, + MovementDirection movementDirection); + + /// + /// Change the sprite to show an animation. + /// + /// Elapsed game time is used for calculating FPS. + void PlayAnimation(GameTime gameTime); + + /// + /// Plays the specified animation fully, but only once. + /// + /// For which movement state the animation should be played. + /// How long (or how slow) should the animation be? + void PlayOnce(MovementState animation, TimeSpan duration); + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/KingSprite.cs b/V3/Objects/Sprite/KingSprite.cs new file mode 100644 index 0000000..0640514 --- /dev/null +++ b/V3/Objects/Sprite/KingSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class KingSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "king"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/LongswordFemaleSprite.cs b/V3/Objects/Sprite/LongswordFemaleSprite.cs new file mode 100644 index 0000000..fc10b7c --- /dev/null +++ b/V3/Objects/Sprite/LongswordFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class LongswordFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "longsword_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/LongswordSprite.cs b/V3/Objects/Sprite/LongswordSprite.cs new file mode 100644 index 0000000..7ac1850 --- /dev/null +++ b/V3/Objects/Sprite/LongswordSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class LongswordSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "longsword"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/MeatballSprite.cs b/V3/Objects/Sprite/MeatballSprite.cs new file mode 100644 index 0000000..eeafbe9 --- /dev/null +++ b/V3/Objects/Sprite/MeatballSprite.cs @@ -0,0 +1,11 @@ +namespace V3.Objects.Sprite +{ + public sealed class MeatballSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "fleischklops"; + protected override int AttackingFrames { get; } = 12; + protected override int DyingFrames { get; } = 8; + protected override int AttackingTextureIndex { get; } = 12; + protected override int DyingTextureIndex { get; } = 24; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/NecromancerFemaleSprite.cs b/V3/Objects/Sprite/NecromancerFemaleSprite.cs new file mode 100644 index 0000000..ffecd74 --- /dev/null +++ b/V3/Objects/Sprite/NecromancerFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class NecromancerFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "necromancer_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/NecromancerSprite.cs b/V3/Objects/Sprite/NecromancerSprite.cs new file mode 100644 index 0000000..494ba13 --- /dev/null +++ b/V3/Objects/Sprite/NecromancerSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class NecromancerSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "necromancer"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/NudeFemaleSprite.cs b/V3/Objects/Sprite/NudeFemaleSprite.cs new file mode 100644 index 0000000..e2aaa2f --- /dev/null +++ b/V3/Objects/Sprite/NudeFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class NudeFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "nude_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/NudeSprite.cs b/V3/Objects/Sprite/NudeSprite.cs new file mode 100644 index 0000000..1056335 --- /dev/null +++ b/V3/Objects/Sprite/NudeSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class NudeSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "nude"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/PlateFemaleSprite.cs b/V3/Objects/Sprite/PlateFemaleSprite.cs new file mode 100644 index 0000000..af3bd79 --- /dev/null +++ b/V3/Objects/Sprite/PlateFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class PlateFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "plate_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/PlateSprite.cs b/V3/Objects/Sprite/PlateSprite.cs new file mode 100644 index 0000000..c8495a0 --- /dev/null +++ b/V3/Objects/Sprite/PlateSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class PlateSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "plate"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/PrinceSprite.cs b/V3/Objects/Sprite/PrinceSprite.cs new file mode 100644 index 0000000..efe9d18 --- /dev/null +++ b/V3/Objects/Sprite/PrinceSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class PrinceSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "prince"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ShieldFemaleSprite.cs b/V3/Objects/Sprite/ShieldFemaleSprite.cs new file mode 100644 index 0000000..0e70545 --- /dev/null +++ b/V3/Objects/Sprite/ShieldFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ShieldFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "shield_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ShieldSprite.cs b/V3/Objects/Sprite/ShieldSprite.cs new file mode 100644 index 0000000..5830a45 --- /dev/null +++ b/V3/Objects/Sprite/ShieldSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public sealed class ShieldSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "shield"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ShortswordFemaleSprite.cs b/V3/Objects/Sprite/ShortswordFemaleSprite.cs new file mode 100644 index 0000000..a046bb0 --- /dev/null +++ b/V3/Objects/Sprite/ShortswordFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class ShortswordFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "shortsword_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ShortswordSprite.cs b/V3/Objects/Sprite/ShortswordSprite.cs new file mode 100644 index 0000000..352631f --- /dev/null +++ b/V3/Objects/Sprite/ShortswordSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class ShortswordSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "shortsword"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/SkeletonArcherSprite.cs b/V3/Objects/Sprite/SkeletonArcherSprite.cs new file mode 100644 index 0000000..1891939 --- /dev/null +++ b/V3/Objects/Sprite/SkeletonArcherSprite.cs @@ -0,0 +1,10 @@ +namespace V3.Objects.Sprite +{ + public class SkeletonArcherSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "skeleton_archer"; + protected override int AttackingFrames { get; } = 4; + protected override int AttackingTextureIndex { get; } = 28; + protected override int DyingTextureIndex { get; } = 22; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/SkeletonEliteSprite.cs b/V3/Objects/Sprite/SkeletonEliteSprite.cs new file mode 100644 index 0000000..99aa94b --- /dev/null +++ b/V3/Objects/Sprite/SkeletonEliteSprite.cs @@ -0,0 +1,9 @@ +namespace V3.Objects.Sprite +{ + public class SkeletonEliteSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "skeleton_elite"; + protected override int AttackingFrames { get; } = 4; + protected override int DyingTextureIndex { get; } = 22; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/SkeletonHorseSprite.cs b/V3/Objects/Sprite/SkeletonHorseSprite.cs new file mode 100644 index 0000000..f26b58b --- /dev/null +++ b/V3/Objects/Sprite/SkeletonHorseSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class SkeletonHorseSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "skeleton_horse"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/SkeletonRiderSprite.cs b/V3/Objects/Sprite/SkeletonRiderSprite.cs new file mode 100644 index 0000000..278d8c7 --- /dev/null +++ b/V3/Objects/Sprite/SkeletonRiderSprite.cs @@ -0,0 +1,10 @@ +namespace V3.Objects.Sprite +{ + public class SkeletonRiderSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "skeleton_rider"; + protected override int AttackingFrames { get; } = 5; + protected override int DyingTextureIndex { get; } = 0; + protected override int DyingFrames { get; } = 0; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/SkeletonSprite.cs b/V3/Objects/Sprite/SkeletonSprite.cs new file mode 100644 index 0000000..15f7246 --- /dev/null +++ b/V3/Objects/Sprite/SkeletonSprite.cs @@ -0,0 +1,9 @@ +namespace V3.Objects.Sprite +{ + public sealed class SkeletonSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "skeleton"; + protected override int AttackingFrames { get; } = 4; + protected override int DyingTextureIndex { get; } = 22; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/StaffFemaleSprite.cs b/V3/Objects/Sprite/StaffFemaleSprite.cs new file mode 100644 index 0000000..5e4120c --- /dev/null +++ b/V3/Objects/Sprite/StaffFemaleSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class StaffFemaleSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "staff_female"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/StaffSprite.cs b/V3/Objects/Sprite/StaffSprite.cs new file mode 100644 index 0000000..aac7bed --- /dev/null +++ b/V3/Objects/Sprite/StaffSprite.cs @@ -0,0 +1,7 @@ +namespace V3.Objects.Sprite +{ + public class StaffSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "staff"; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ZombieSprite.cs b/V3/Objects/Sprite/ZombieSprite.cs new file mode 100644 index 0000000..0cd1a19 --- /dev/null +++ b/V3/Objects/Sprite/ZombieSprite.cs @@ -0,0 +1,11 @@ +namespace V3.Objects.Sprite +{ + public sealed class ZombieSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "zombie"; + protected override int AttackingFrames { get; } = 8; + protected override int DyingTextureIndex { get; } = 22; + protected override int SpecialTextureIndex { get; } = 36; + protected override int SpecialFrames { get; } = 8; + } +} \ No newline at end of file diff --git a/V3/Objects/Sprite/ZombieWithClubSprite.cs b/V3/Objects/Sprite/ZombieWithClubSprite.cs new file mode 100644 index 0000000..60abc24 --- /dev/null +++ b/V3/Objects/Sprite/ZombieWithClubSprite.cs @@ -0,0 +1,11 @@ +namespace V3.Objects.Sprite +{ + public sealed class ZombieWithClubSprite : AbstractSpriteCreature + { + protected override string TextureFile { get; } = "zombie_club"; + protected override int AttackingFrames { get; } = 8; + protected override int DyingTextureIndex { get; } = 22; + protected override int SpecialTextureIndex { get; } = 36; + protected override int SpecialFrames { get; } = 8; + } +} \ No newline at end of file diff --git a/V3/Objects/TextureObject.cs b/V3/Objects/TextureObject.cs new file mode 100644 index 0000000..b7da6c0 --- /dev/null +++ b/V3/Objects/TextureObject.cs @@ -0,0 +1,76 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using System; + +namespace V3.Objects +{ + /// + /// Texture objects represent map data like tiles and map objects which are placed on the screen. + /// + public sealed class TextureObject : IGameObject + { + public Vector2 Position { get; set; } + public int Id { get; } + public Rectangle BoundaryRectangle => new Rectangle(mDrawPosition, mTextureSize); + private readonly string mTextureName; + private readonly Point mDrawPosition; + private readonly Point mTextureSize; + private Texture2D mTexture; + private readonly Point mTextureSource; + + /// + /// Creates an empty TextureObject. + /// + public TextureObject() + { + Id = IdGenerator.GetNextId(); + Position = Vector2.Zero; + mDrawPosition = Point.Zero; + mTextureSize = Point.Zero; + mTextureName = "EmptyPixel"; + mTextureSource = Point.Zero; + } + + public TextureObject(Point position, Point drawPosition, Point textureSize, Point textureSource, string textureName) + { + Position = position.ToVector2(); + mDrawPosition = drawPosition; + mTextureSize = textureSize; + mTextureName = textureName; + mTextureSource = textureSource; + } + + public void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Textures/" + mTextureName); + //mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); + } + + public void Draw(SpriteBatch spriteBatch) + { + spriteBatch.Draw(mTexture, BoundaryRectangle, new Rectangle(mTextureSource, mTextureSize), Color.White); + } + + public IGameObject GetSelf() + { + return this; + } + + public override bool Equals(Object obj) + { + if (obj == null) + return false; + if (obj == this) + return true; + if (!(obj is IGameObject)) + return false; + return Id.Equals(((IGameObject) obj).Id); + } + + public override int GetHashCode() + { + return Id; + } + } +} diff --git a/V3/Objects/Transformation.cs b/V3/Objects/Transformation.cs new file mode 100644 index 0000000..1b1cf86 --- /dev/null +++ b/V3/Objects/Transformation.cs @@ -0,0 +1,102 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; + +namespace V3.Objects +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class Transformation + { + public IObjectsManager ObjectsManager { private get; set; } + private KeyboardState mOldStateSpecialattack; + private KeyboardState mOldStateZombie; + private KeyboardState mOldStateMeatball; + private KeyboardState mOldStateSkeleton; + private KeyboardState mOldStateHorse; + internal Selection mSelection; + private Texture2D mNecroArea; + + /// + /// Call for transformations + /// + public void Transform() + { + KeyboardState newState = Keyboard.GetState(); + + // Specialattack for Meatball (press 1) + if (newState.IsKeyDown(Keys.D1)) + { + if (!mOldStateSpecialattack.IsKeyDown(Keys.D1)) + { + mSelection.Specialattack(); + } + } + mOldStateSpecialattack = newState; + + // Transform Zombie (press 2) + if (newState.IsKeyDown(Keys.D2)) + { + if (!mOldStateZombie.IsKeyDown(Keys.D2)) + { + mSelection.TransformZombie(); + } + } + mOldStateZombie = newState; + + // Transform Meatball (press 3) + // Nneed five zombies + if (newState.IsKeyDown(Keys.D3)) + { + if (!mOldStateMeatball.IsKeyDown(Keys.D3)) + { + mSelection.TransformMeatball(); + } + } + mOldStateMeatball = newState; + + // Transform Skeleton (press 4) + // Need one zombie + if (newState.IsKeyDown(Keys.D4)) + { + if (!mOldStateSkeleton.IsKeyDown(Keys.D4)) + { + mSelection.TransformSkeleton(); + } + } + mOldStateSkeleton = newState; + + // Transform SkeletonHorse (press 5) + // Nneed 3 skeletons + if (newState.IsKeyDown(Keys.D5)) + { + if (!mOldStateHorse.IsKeyDown(Keys.D5)) + { + mSelection.TransformSkeletonHorse(); + } + } + mOldStateHorse = newState; + } + + //Draw(SpriteBatch spriteBatch, Vector2 position, MovementState movementState, MovementDirection movementDirection) + /// + /// Load the selection and ellipse sprites for necromancers area + /// + /// the content manager + public void LoadArea(ContentManager contentManager) + { + //mNecroArea = contentManager.Load("Sprites/selection"); + mNecroArea = contentManager.Load("Sprites/ellipse"); + } + + /// + /// Draw the area for necromancer + /// + /// the sprite batch to use for drawing the object + public void DrawNecroArea(SpriteBatch spriteBatch) + { + //spriteBatch.Draw(mNecroArea, ObjectsManager.PlayerCharacter.Position - new Vector2(800, 400), null, Color.Red*0.3f, 0, Vector2.Zero, 25, SpriteEffects.None, 0); + spriteBatch.Draw(mNecroArea, ObjectsManager.PlayerCharacter.Position - new Vector2(640, 320), null, Color.Red*0.5f, 0, Vector2.Zero, 2.5f, SpriteEffects.None, 0); + } + } +} \ No newline at end of file diff --git a/V3/Objects/Woodhouse.cs b/V3/Objects/Woodhouse.cs new file mode 100644 index 0000000..82c961b --- /dev/null +++ b/V3/Objects/Woodhouse.cs @@ -0,0 +1,16 @@ +using Microsoft.Xna.Framework; + +namespace V3.Objects +{ + public sealed class Woodhouse : AbstractBuilding + { + public override string Name { get; } = "Holzhaus"; + protected override int MaxRobustness { get; } = 130; + public override int Robustness { get; protected set; } = 130; + public override int MaxGivesWeapons { get; protected set; } = 10; + + public Woodhouse(Vector2 position, Rectangle size, string textureName, BuildingFace facing) : base(position, size, textureName, facing) + { + } + } +} diff --git a/V3/Objects/Zombie.cs b/V3/Objects/Zombie.cs new file mode 100644 index 0000000..635634c --- /dev/null +++ b/V3/Objects/Zombie.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.Xna.Framework.Content; +using V3.Data; +using V3.Map; +using V3.Objects.Movement; +using V3.Objects.Sprite; + +namespace V3.Objects +{ + /// + /// A simple zombie controlled by the necromancer. + /// + public sealed class Zombie : AbstractCreature + { + public override string Name { get; protected set; } = "Zombie"; + public override int Life { get; protected set; } = 150; + public override int MaxLife { get; protected set; } = 150; + public override int Speed { get; } = 5; + public override int Attack { get; protected set; } = 8; + public override int AttackRadius { get; protected set; } = 48; + public override int SightRadius { get; protected set; } = 150; + public override TimeSpan TotalRecovery { get; } = TimeSpan.FromSeconds(1); + public override TimeSpan Recovery { get; set; } + protected override ISpriteCreature[] Sprite { get; } = {new ZombieSprite()}; + protected override IMovable MovementScheme { get; } = new PlayerMovement(); + protected override CreatureType Type { get; } = CreatureType.Zombie; + public override Faction Faction { get; } = Faction.Undead; + public override ICreature IsAttacking { get; set; } + public override IBuilding IsAttackingBuilding { get; set; } + + public Zombie(ContentManager contentManager, + Pathfinder pathfinder, IOptionsManager optionsManager, AchievementsAndStatistics achievementsAndStatistics) + : base(contentManager, pathfinder, optionsManager,achievementsAndStatistics) + { + } + + public override void LoadData(CreatureData data) + { + base.LoadData(data); + + if (IsUpgraded) + ChangeEquipment(EquipmentType.Body, new ZombieWithClubSprite()); + } + } +} diff --git a/V3/OpenTK.dll.config b/V3/OpenTK.dll.config new file mode 100644 index 0000000..3f888cc --- /dev/null +++ b/V3/OpenTK.dll.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/V3/Program.cs b/V3/Program.cs new file mode 100644 index 0000000..aa1fdcd --- /dev/null +++ b/V3/Program.cs @@ -0,0 +1,20 @@ +using System; + +namespace V3 +{ + /// + /// The main class. + /// + public static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + using (var game = new V3Game()) + game.Run(); + } + } +} diff --git a/V3/Properties/AssemblyInfo.cs b/V3/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4f905d4 --- /dev/null +++ b/V3/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("V3")] +[assembly: AssemblyProduct("V3")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0c41bf76-037f-47fb-b16a-0c32567c6067")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/V3/Quadtree.cs b/V3/Quadtree.cs new file mode 100644 index 0000000..dfc088f --- /dev/null +++ b/V3/Quadtree.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Objects; + +namespace V3 +{ + public sealed class Quadtree + { + private Node mRoot; // The first "Node" of the Quadtree + private ContentManager mContentManager; + private readonly Point mMaxSize; + + /// + /// Generates Quadtree + /// + /// Gives the biggest/first Rectangle of the Quadtree. This should be the sice of the howl map. + public Quadtree(Point maxSize) + { + mRoot = new Node(new Rectangle(new Point(-128, -128), maxSize), null); + mMaxSize = maxSize; + } + + /// + /// Updates the Quadtree. This is importent for the movements of the Objects. + /// + public void Update() + { + mRoot.Update1(); + } + + /// + /// You call this method if you want to Inster an Object to the Quadtree. + /// + /// Type of Creature including their position. + public void Insert(IGameObject item) + { + mRoot.AddtoSubNode(item); + } + + /// + /// DMakes the Rectangles of the Quadtree visible. + /// + /// + public void Draw(SpriteBatch spriteBatch) + { + mRoot.DrawQuadtree(spriteBatch, Texture); + } + + public List GetObjectsInRectangle(Rectangle rectangle) + { + List objectList = new List(); + return mRoot.GetObjectsInRectangle(rectangle, objectList); + } + + /// + /// Deletes an Object out of the Quadtree. + /// + /// Type of Creature including their position. + public void RemoveItem(IGameObject item) + { + mRoot.Delete(item); + } + + /// + /// Loads the content to draw the Rectangels of the Quadtree. + /// + /// + public void LoadContent(ContentManager contentManager) + { + mContentManager = contentManager; + Texture = mContentManager.Load("Sprites/WhiteRectangle"); + } + + /// + /// Deletes all elements from the quadtree. + /// + public void Clear() + { + mRoot?.Clear(); + mRoot = new Node(new Rectangle(new Point(-50, -50), mMaxSize), null); + } + + private Texture2D Texture { get; set; } + } +} diff --git a/V3/Screens/AbstractScreen.cs b/V3/Screens/AbstractScreen.cs new file mode 100644 index 0000000..becd38d --- /dev/null +++ b/V3/Screens/AbstractScreen.cs @@ -0,0 +1,57 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using V3.Input; + +namespace V3.Screens +{ + public abstract class AbstractScreen : IScreen + { + /// + /// Indicates whether screens below this one should be updated. + /// + public bool UpdateLower { get; } + + /// + /// Indicates whether screens below this one should be drawn. + /// + public bool DrawLower { get; } + + protected AbstractScreen(bool updateLower, bool drawLower) + { + UpdateLower = updateLower; + DrawLower = drawLower; + } + + /// + /// Handles the given key event and returns whether it should be passed + /// to the screens below this one. + /// + /// the key event that occurred + /// true if the event has been handeled by this screen and + /// should not be passed to the lower screens, false otherwise + public virtual bool HandleKeyEvent(IKeyEvent keyEvent) + { + return false; + } + + /// + /// Handles the given mouse event and returns whether it should be passed + /// to the screens below this one. + /// + /// the mouse event that occurred + /// true if the event has been handeled by this screen and + /// should not be passed to the lower screens, false otherwise + public virtual bool HandleMouseEvent(IMouseEvent mouseEvent) + { + return true; + } + + public virtual void Update(GameTime gameTime) + { + } + + public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) + { + } + } +} diff --git a/V3/Screens/AchievementsScreen.cs b/V3/Screens/AchievementsScreen.cs new file mode 100644 index 0000000..096fb81 --- /dev/null +++ b/V3/Screens/AchievementsScreen.cs @@ -0,0 +1,221 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Ninject; +using V3.Input; +using V3.Objects; +using V3.Widgets; + +namespace V3.Screens +{ + /// + /// The screen for the AchievementsAndStatistics. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class AchievementsScreen : AbstractScreen, IInitializable + { + //private AchievementBox mFirstSteps; + private AchievementBox mKillPrince; + private AchievementBox mKillKing; + //private AchievementBox mWarmasterAndWizard; + private AchievementBox mKaboom; + private AchievementBox mMarathonRunner; + private AchievementBox mIronMan; + private AchievementBox mMeatballCompany; + private AchievementBox mSkeletonHorseCavalry; + private AchievementBox mRightHandOfDeath; + private AchievementBox mMinimalist; + private AchievementBox mHundredDeadCorpses; + private AchievementBox mUndeadArmy; + private AchievementBox mHellsNotWaiting; + + + private readonly ContentManager mContentManager; + private readonly IMenuFactory mMenuFactory; + private readonly MenuActions mMenuActions; + private readonly WidgetFactory mWidgetFactory; + private readonly AchievementsAndStatistics mAchievementsAndStatistics; + private readonly ObjectsManager mObjectsManager; + + private Button mButtonBack; + private SelectButton mSelectPage; + + private List mMenuList = new List(); + private Texture2D mRectangle; + + public AchievementsScreen(ContentManager contentManager, MenuActions menuActions, WidgetFactory widgetFactory, + IMenuFactory menuFactory, AchievementsAndStatistics achievementsAndStatistics, ObjectsManager objectsManager) + : base(false, true) + { + mContentManager = contentManager; + mMenuFactory = menuFactory; + mMenuActions = menuActions; + mWidgetFactory = widgetFactory; + mAchievementsAndStatistics = achievementsAndStatistics; + mObjectsManager = objectsManager; + } + + public void Initialize() + { + mRectangle = mContentManager.Load("Sprites/WhiteRectangle"); + + mButtonBack = mWidgetFactory.CreateButton("Zurück"); + mSelectPage = mWidgetFactory.CreateSelectButton(); + + var menu = mMenuFactory.CreateVerticalMenu(); + mMenuList.Add(menu); + + menu.Widgets.Add(mSelectPage); + + mKillPrince = mWidgetFactory.CreateAchievementBox(); + mKillPrince.SetText("Erbfolge aufgehalten", "Vernichtet Prinz Erhard."); + menu.Widgets.Add(mKillPrince); + + mKaboom = mWidgetFactory.CreateAchievementBox(); + mKaboom.SetText("KABUMM!!!", "Tötet mindestens 10 Gegner mit einer einzigen Fleischklops-Explosion."); + menu.Widgets.Add(mKaboom); + + mKillKing = mWidgetFactory.CreateAchievementBox(); + mKillKing.SetText("Königsmord", "Nehmt eure Vergeltung am König und tötet ihn."); + menu.Widgets.Add(mKillKing); + + menu.Widgets.Add(mButtonBack); + + menu = mMenuFactory.CreateVerticalMenu(); + mMenuList.Add(menu); + + menu.Widgets.Add(mSelectPage); + + mHundredDeadCorpses = mWidgetFactory.CreateAchievementBox(); + mHundredDeadCorpses.SetText("Leichenfledderer", "Tötet in einer Mission mindestens 100 Gegner."); + menu.Widgets.Add(mHundredDeadCorpses); + + mUndeadArmy = mWidgetFactory.CreateAchievementBox(); + mUndeadArmy.SetText("Untote Armee", "Tötet in einer Mission mindestens 1000 Gegner."); + menu.Widgets.Add(mUndeadArmy); + + mRightHandOfDeath = mWidgetFactory.CreateAchievementBox(); + mRightHandOfDeath.SetText("Die erbarmungslose rechte Hand des Todes", "Tötet insgesamt 10 000 Gegner."); + menu.Widgets.Add(mRightHandOfDeath); + + menu.Widgets.Add(mButtonBack); + + menu = mMenuFactory.CreateVerticalMenu(); + mMenuList.Add(menu); + + menu.Widgets.Add(mSelectPage); + + mMeatballCompany = mWidgetFactory.CreateAchievementBox(); + mMeatballCompany.SetText("Fleischpanzer-Kompanie", "Erschafft und befehligt in einer Mission 10 Fleischklopse gleichzeitig."); + menu.Widgets.Add(mMeatballCompany); + + mSkeletonHorseCavalry = mWidgetFactory.CreateAchievementBox(); + mSkeletonHorseCavalry.SetText("Klappernde Kavallerie", "Erschafft und befehligt in einer Mission 25 Skelettpferde gleichzeitig."); + menu.Widgets.Add(mSkeletonHorseCavalry); + + mMinimalist = mWidgetFactory.CreateAchievementBox(); + mMinimalist.SetText("Minimalist", "Beendet eine Mission und setzt dabei weniger als 100 Einheiten ein."); + menu.Widgets.Add(mMinimalist); + + menu.Widgets.Add(mButtonBack); + + menu = mMenuFactory.CreateVerticalMenu(); + mMenuList.Add(menu); + + menu.Widgets.Add(mSelectPage); + + mHellsNotWaiting = mWidgetFactory.CreateAchievementBox(); + mHellsNotWaiting.SetText("Die Hölle wartet nicht", "Beendet eine Mission in weniger als 5 Minuten."); + menu.Widgets.Add(mHellsNotWaiting); + + mMarathonRunner = mWidgetFactory.CreateAchievementBox(); + mMarathonRunner.SetText("Marathonläufer", "Legt in einer Mission mindestens 1000m zurück."); + menu.Widgets.Add(mMarathonRunner); + + mIronMan = mWidgetFactory.CreateAchievementBox(); + mIronMan.SetText("Der Iron Man", "Legt insgesamt eine Strecke von 10 000m zurück."); + menu.Widgets.Add(mIronMan); + + menu.Widgets.Add(mButtonBack); + + for (var i = 0; i < mMenuList.Count; i++) + mSelectPage.Values.Add($"Seite {i + 1}"); + } + + public override bool HandleKeyEvent(IKeyEvent keyEvent) + { + if (keyEvent.KeyState == KeyState.Down && keyEvent.Key == Keys.Escape) + mMenuActions.Close(this); + + return true; + } + + public override bool HandleMouseEvent(IMouseEvent mouseEvent) + { + GetCurrentMenu().HandleMouseEvent(mouseEvent); + return true; + } + + public override void Update(GameTime gameTime) + { + if (mButtonBack.IsClicked) + { + mMenuActions.Close(this); + } + GetCurrentMenu().Update(); + + // achievement datas. if one value becomes a given value, the corresponding achievement will be enabled. + + if (mAchievementsAndStatistics.mKillPrince) + mKillPrince.IsEnabled = true; + if (mAchievementsAndStatistics.mKillKing) + mKillKing.IsEnabled = true; + if (mAchievementsAndStatistics.mHellsNotWaiting) + mHellsNotWaiting.IsEnabled = true; + if (mAchievementsAndStatistics.mKaboom) + mKaboom.IsEnabled = true; + + if (mAchievementsAndStatistics.mMarathonRunner >= 1000) + mMarathonRunner.IsEnabled = true; + if (mAchievementsAndStatistics.mIronMan >= 10000) + mIronMan.IsEnabled = true; + if (mAchievementsAndStatistics.mMeatballCompany >= 10) + mMeatballCompany.IsEnabled = true; + if (mAchievementsAndStatistics.mSkeletonHorseCavalry >= 25) + mSkeletonHorseCavalry.IsEnabled = true; + if (mAchievementsAndStatistics.mRightHandOfDeath >= 10000) + mRightHandOfDeath.IsEnabled = true; + if (mAchievementsAndStatistics.mMinimalist <= 100 && mObjectsManager.Boss != null && mObjectsManager.Boss.IsDead) + mMinimalist.IsEnabled = true; + if (mAchievementsAndStatistics.mHundredDeadCorpses >= 100) + mHundredDeadCorpses.IsEnabled = true; + if (mAchievementsAndStatistics.mUndeadArmy >= 1000) + mUndeadArmy.IsEnabled = true; + } + + public override void Draw(GameTime gameTime, SpriteBatch spriteBatch) + { + var menu = GetCurrentMenu(); + var backgroundRectangle = new Rectangle((int)menu.Position.X, + (int)menu.Position.Y, (int)menu.Size.X, + (int)menu.Size.Y); + backgroundRectangle.X -= 30; + backgroundRectangle.Y -= 30; + backgroundRectangle.Width += 60; + backgroundRectangle.Height += 60; + + spriteBatch.Begin(); + spriteBatch.Draw(mRectangle, backgroundRectangle, Color.WhiteSmoke); + spriteBatch.End(); + + menu.Draw(spriteBatch); + } + + private IMenu GetCurrentMenu() + { + return mMenuList[mSelectPage.SelectedIndex]; + } + } +} diff --git a/V3/Screens/DeathScreen.cs b/V3/Screens/DeathScreen.cs new file mode 100644 index 0000000..230d40a --- /dev/null +++ b/V3/Screens/DeathScreen.cs @@ -0,0 +1,140 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Ninject; +using V3.Input; +using V3.Widgets; + +namespace V3.Screens +{ + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class DeathScreen : AbstractScreen, IInitializable + { + private static TimeSpan sTotalDelay = TimeSpan.FromSeconds(2); + + private readonly ContentManager mContentManager; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + private readonly MenuActions mMenuActions; + private readonly WidgetFactory mWidgetFactory; + + private Button mMenuButton; + private Button mCloseGameButton; + private Vector2 mButtonPosition; + private Vector2 mCenter; + private Vector2 mFontCenter; + private SpriteFont mDeathFont; + private Texture2D mRectangle; + + private TimeSpan mDelayTimer = sTotalDelay; + + /// + /// Creates a death screen if the players health reaches 0. + /// + + public DeathScreen(ContentManager contentManager, + GraphicsDeviceManager graphicsDeviceManager, + MenuActions menuActions, + WidgetFactory widgetFactory) + : base(false, true) + { + mContentManager = contentManager; + mGraphicsDeviceManager = graphicsDeviceManager; + mMenuActions = menuActions; + mWidgetFactory = widgetFactory; + } + + public override bool HandleKeyEvent(IKeyEvent keyEvent) + { + return false; + } + + public override bool HandleMouseEvent(IMouseEvent mouseEvent) + { + if (mDelayTimer <= TimeSpan.Zero) + { + mMenuButton.HandleMouseEvent(mouseEvent); + mCloseGameButton.HandleMouseEvent(mouseEvent); + } + return false; + } + + public void Initialize() + { + mRectangle = mContentManager.Load("Sprites/WhiteRectangle"); + mDeathFont = mContentManager.Load("Fonts/DeathFont"); + + mMenuButton = mWidgetFactory.CreateButton("Zum Hauptmenü"); + mMenuButton.Position = Vector2.Zero; + mMenuButton.PaddingX = 10; + mMenuButton.PaddingY = 0; + mMenuButton.Size = mMenuButton.GetMinimumSize(); + mMenuButton.BackgroundColor = Color.Gray * 0.7f; + + mCloseGameButton = mWidgetFactory.CreateButton("Spiel schließen"); + mCloseGameButton.Position = Vector2.Zero; + mCloseGameButton.PaddingX = 10; + mCloseGameButton.PaddingY = 0; + mCloseGameButton.Size = mCloseGameButton.GetMinimumSize(); + mCloseGameButton.BackgroundColor = Color.Gray * 0.7f; + } + + public override void Update(GameTime gameTime) + { + var viewport = mGraphicsDeviceManager.GraphicsDevice.Viewport; + + mCenter = new Vector2(viewport.Width / 2f, viewport.Height / 2f); + mFontCenter = mDeathFont.MeasureString("Ihr seid tot") / 2; + mButtonPosition = new Vector2(mCenter.X - mFontCenter.X * 2/3, mCenter.Y + mFontCenter.Y * 2); + + if (mDelayTimer > TimeSpan.Zero) + mDelayTimer -= gameTime.ElapsedGameTime; + + mMenuButton.Position = mButtonPosition; + mCloseGameButton.Position = mMenuButton.Position + new Vector2(mFontCenter.X * 3/ 4, 0); + + if (mMenuButton.IsClicked) + { + mMenuActions.OpenMainScreen(); + } + else if (mCloseGameButton.IsClicked) + { + mMenuActions.Exit(); + } + + mMenuButton.IsSelected = mMenuButton.CheckSelected(Mouse.GetState().Position); + mMenuButton.IsClicked = false; + + mCloseGameButton.IsSelected = mCloseGameButton.CheckSelected(Mouse.GetState().Position); + mCloseGameButton.IsClicked = false; + } + + public override void Draw(GameTime gameTime, SpriteBatch spriteBatch) + { + float displayRatio = (float) (1 - mDelayTimer.TotalMilliseconds / sTotalDelay.TotalMilliseconds); + + spriteBatch.Begin(); + spriteBatch.Draw(mRectangle, + mGraphicsDeviceManager.GraphicsDevice.Viewport.Bounds, + Color.Black * 0.5f * displayRatio); + + spriteBatch.DrawString(mDeathFont, + "Ihr seid tot", + mCenter, + Color.Firebrick * displayRatio, + 0, + mFontCenter, + 1.0f, + SpriteEffects.None, + 0.5f); + + if (mDelayTimer <= TimeSpan.Zero) + { + mMenuButton.Draw(spriteBatch); + mCloseGameButton.Draw(spriteBatch); + } + spriteBatch.End(); + } + } +} diff --git a/V3/Screens/DebugScreen.cs b/V3/Screens/DebugScreen.cs new file mode 100644 index 0000000..a1e0820 --- /dev/null +++ b/V3/Screens/DebugScreen.cs @@ -0,0 +1,92 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Ninject; +using V3.Data; +using V3.Input; +using V3.Objects; +using V3.Widgets; + +namespace V3.Screens +{ + /// + /// A special screen that counts and show the number of frames per + /// second (if debug is enabled). This screen is not added to the + /// screen stack, but is always drawn and updated by the screen manager. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class DebugScreen : AbstractScreen, IInitializable + { + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + private readonly IObjectsManager mObjectsManager; + private readonly IOptionsManager mOptionsManager; + private readonly WidgetFactory mWidgetFactory; + private FpsCounter mFpsCounter; + private Label mFpsLabel; + private Label mUnitCountLabel; + private int mUnitCount; + + /// + /// Creates a new debug screen. + /// + public DebugScreen(GraphicsDeviceManager graphicsDeviceManager, + IObjectsManager objectsManager, IOptionsManager optionsManager, + WidgetFactory widgetFactory) : base(true, true) + { + mGraphicsDeviceManager = graphicsDeviceManager; + mObjectsManager = objectsManager; + mOptionsManager = optionsManager; + mWidgetFactory = widgetFactory; + } + + public void Initialize() + { + mFpsCounter = new FpsCounter(); + + mFpsLabel = mWidgetFactory.CreateLabel(""); + mFpsLabel.PaddingX = 10; + mFpsLabel.PaddingY = 0; + mFpsLabel.HorizontalOrientation = HorizontalOrientation.Left; + mFpsLabel.Color = Color.Red; + + mUnitCountLabel = mWidgetFactory.CreateLabel(""); + mUnitCountLabel.PaddingX = 10; + mUnitCountLabel.PaddingY = 0; + mUnitCountLabel.HorizontalOrientation = HorizontalOrientation.Left; + mUnitCountLabel.Color = Color.Red; + } + + public override bool HandleMouseEvent(IMouseEvent mouseEvent) + { + return false; + } + + public override void Update(GameTime gameTime) + { + mFpsCounter.Update(gameTime); + mUnitCount = mObjectsManager.CreatureList?.Count ?? 0; + } + + public override void Draw(GameTime gameTime, SpriteBatch spriteBatch) + { + mFpsCounter.AddFrame(); + + if (mOptionsManager.Options.DebugMode == DebugMode.Off) + return; + + var viewport = mGraphicsDeviceManager.GraphicsDevice.Viewport; + + mFpsLabel.Text = $"FPS: {mFpsCounter.Fps} " + (gameTime.IsRunningSlowly ? "!" : ""); + mFpsLabel.Size = mFpsLabel.GetMinimumSize(); + mFpsLabel.Position = new Vector2(0, viewport.Height - mFpsLabel.Size.Y); + + mUnitCountLabel.Text = $"# units: {mUnitCount}"; + mUnitCountLabel.Size = mUnitCountLabel.GetMinimumSize(); + mUnitCountLabel.Position = mFpsLabel.Position - new Vector2(0, mFpsLabel.Size.Y); + + spriteBatch.Begin(); + mFpsLabel.Draw(spriteBatch); + mUnitCountLabel.Draw(spriteBatch); + spriteBatch.End(); + } + } +} diff --git a/V3/Screens/FpsCounter.cs b/V3/Screens/FpsCounter.cs new file mode 100644 index 0000000..5c3ac0c --- /dev/null +++ b/V3/Screens/FpsCounter.cs @@ -0,0 +1,46 @@ +using System; +using Microsoft.Xna.Framework; + +namespace V3.Screens +{ + /// + /// Counts the frames per second based on the elapsed time and the number + /// of frames that have been drawn. Call Update in each Update, and + /// AddFrame in each Draw. + /// + public sealed class FpsCounter + { + /// + /// The current frames per second. + /// + public int Fps { get; private set; } + + private int mFrameCount; + private TimeSpan mTimeSpan = TimeSpan.Zero; + + /// + /// Updates the elapsed time and -- once every second -- the fps value. + /// + /// the elapsed game time + public void Update(GameTime gameTime) + { + mTimeSpan += gameTime.ElapsedGameTime; + + if (mTimeSpan > TimeSpan.FromSeconds(1)) + { + mTimeSpan -= TimeSpan.FromSeconds(1); + Fps = mFrameCount; + mFrameCount = 0; + } + } + + /// + /// Registers that a frame has been drawn. Should be called once for + /// every Draw. + /// + public void AddFrame() + { + mFrameCount++; + } + } +} diff --git a/V3/Screens/GameScreen.cs b/V3/Screens/GameScreen.cs new file mode 100644 index 0000000..e37b100 --- /dev/null +++ b/V3/Screens/GameScreen.cs @@ -0,0 +1,306 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Ninject; +using System.Collections.Generic; +using V3.AI; +using V3.Camera; +using V3.Data; +using V3.Effects; +using V3.Input; +using V3.Map; +using V3.Objects; + +namespace V3.Screens +{ + /// + /// The main game screen. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class GameScreen : AbstractScreen, IInitializable + { + private readonly CameraManager mCameraManager; + private readonly ContentManager mContentManager; + private readonly CreatureFactory mCreatureFactory; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + private readonly MenuActions mMenuActions; + private readonly IOptionsManager mOptionsManager; + private readonly Selection mSelection; + private readonly Transformation mTransformation; + private readonly IAiPlayer mAiPlayer; + private readonly IMapManager mMapManager; + private readonly IEffectsManager mEffectsManager; + private readonly IObjectsManager mObjectsManager; + private readonly Pathfinder mPathfinder; + private readonly Texture2D mOnePixelTexture; + private readonly FogOfWar mFog; + private bool mFogOfWarActivaded = true; + private AchievementsAndStatistics mAchievementsAndStatistics; + private int mFogCounter; + // Fields for handling mouse input. + private Point mInitialClickPosition; + private bool mLeftButtonPressed; + private bool mRightButtonPressed; + private Vector2 mRightButtonPosition; + + /// + /// Creates a new game screen. + /// + public GameScreen(IOptionsManager optionsManager, CameraManager cameraManager, + ContentManager contentManager, CreatureFactory creatureFactory, + GraphicsDeviceManager graphicsDeviceManager, IMapManager mapManager, + MenuActions menuActions, IAiPlayer aiPlayer, IObjectsManager objectsManager, + Pathfinder pathfinder, Selection selection, FogOfWar fog, Transformation transformation, + IEffectsManager effectsManager, AchievementsAndStatistics achievementsAndStatistics) : base(false, false) + { + mMapManager = mapManager; + mObjectsManager = objectsManager; + mCameraManager = cameraManager; + mOptionsManager = optionsManager; + mContentManager = contentManager; + mCreatureFactory = creatureFactory; + mEffectsManager = effectsManager; + mTransformation = transformation; + mGraphicsDeviceManager = graphicsDeviceManager; + mMenuActions = menuActions; + mAiPlayer = aiPlayer; + mPathfinder = pathfinder; + mSelection = selection; + mFog = fog; + mOnePixelTexture = contentManager.Load("Sprites/WhiteRectangle"); + mAchievementsAndStatistics = achievementsAndStatistics; + } + + + public override bool HandleMouseEvent(IMouseEvent mouseEvent) + { + if (mouseEvent.MouseButton == MouseButton.Left && mouseEvent.ButtonState == ButtonState.Pressed) + { + if (!mLeftButtonPressed) + { + mLeftButtonPressed = true; + mInitialClickPosition = mouseEvent.PositionPressed; + } + } + else + { + if (mLeftButtonPressed) + { + mSelection.Select(mInitialClickPosition + mCameraManager.GetCamera().Location.ToPoint(), + mouseEvent.PositionReleased.GetValueOrDefault() + mCameraManager.GetCamera().Location.ToPoint()); + mLeftButtonPressed = false; + } + } + if (mouseEvent.MouseButton == MouseButton.Right && mouseEvent.ButtonState == ButtonState.Pressed) + { + if (!mRightButtonPressed) + { + mRightButtonPressed = true; + mInitialClickPosition = mouseEvent.PositionPressed; + } + } + if (mouseEvent.MouseButton == MouseButton.Right && mouseEvent.ButtonState == ButtonState.Released) + { + if (mouseEvent.PositionReleased != null && mouseEvent.ReleasedOnScreen) + { + mRightButtonPressed = false; + mRightButtonPosition = mouseEvent.PositionReleased.Value.ToVector2() + mCameraManager.GetCamera().Location; + mSelection.Move(mouseEvent.PositionReleased.Value.ToVector2() + + mCameraManager.GetCamera().Location); + } + } + return true; + } + + public void Initialize() + { +#if NEWMAP + mMapManager.Load("work_in_progress"); +#else + mMapManager.Load("map_grassland"); +#endif + mObjectsManager.Initialize(mMapManager); + mCameraManager.Initialize(mMapManager.SizeInPixel); + mPathfinder.LoadGrid(mMapManager.GetPathfindingGrid()); + mFog.LoadContent(mContentManager); + mFog.LoadGrid(mMapManager.SizeInPixel); + mTransformation.mSelection = mSelection; + mTransformation.LoadArea(mContentManager); + mTransformation.ObjectsManager = mObjectsManager; + } + + /// + /// Create the initial population as designated by the map manager, + /// the player character, and possibly other creatures. + /// + public void CreateInitialPopulation() + { + // Create initial population. + foreach (var creature in mMapManager.GetPopulation(mCreatureFactory, mPathfinder)) + { + mObjectsManager.CreateCreature(creature); + } + +#if NEWMAP + var necromancer = mCreatureFactory.CreateNecromancer(new Vector2(385, 420), MovementDirection.S); + mObjectsManager.CreatePlayerCharacter(necromancer); + // Create Prince and his guard. + mObjectsManager.CreatePrince(mCreatureFactory.CreatePrince(new Vector2(6139, 3039), MovementDirection.SO)); + mObjectsManager.CreateCreature(mCreatureFactory.CreateKingsGuard(new Vector2(5794, 2900), MovementDirection.N)); + mObjectsManager.CreateCreature(mCreatureFactory.CreateKingsGuard(new Vector2(5858, 2900), MovementDirection.N)); + mObjectsManager.CreateCreature(mCreatureFactory.CreateKingsGuard(new Vector2(5936, 2885), MovementDirection.NW)); + mObjectsManager.CreateCreature(mCreatureFactory.CreateKingsGuard(new Vector2(6000, 2885), MovementDirection.NW)); + mObjectsManager.CreateCreature(mCreatureFactory.CreateKingsGuard(new Vector2(6064, 2885), MovementDirection.NW)); +#else + // Add creatures for testing purposes. + var necromancer = mCreatureFactory.CreateNecromancer(new Vector2(300, 150), MovementDirection.S); + var zombie1 = mCreatureFactory.CreateZombie(new Vector2(800, 200), MovementDirection.S); + var zombie2 = mCreatureFactory.CreateZombie(new Vector2(850, 250), MovementDirection.S); + var zombie3 = mCreatureFactory.CreateZombie(new Vector2(900, 200), MovementDirection.S); + var zombie4 = mCreatureFactory.CreateZombie(new Vector2(950, 250), MovementDirection.S); + var zombie5 = mCreatureFactory.CreateZombie(new Vector2(1000, 200), MovementDirection.S); + var zombieToGo = mCreatureFactory.CreateZombie(new Vector2(400, 400), MovementDirection.S); + var knight = mCreatureFactory.CreateKnight(new Vector2(1500, 210), MovementDirection.W); + var horse = mCreatureFactory.CreateSkeletonHorse(new Vector2(1300, 500), MovementDirection.SW); + var prince = mCreatureFactory.CreatePrince(new Vector2(1800, 1000), MovementDirection.S); + var meatball = mCreatureFactory.CreateMeatball(new Vector2(350, 150), MovementDirection.S); + // Add creatures to obects manager. + mObjectsManager.CreatePlayerCharacter(necromancer); + mObjectsManager.CreatePrince(prince); + mObjectsManager.CreateCreature(zombie1); + mObjectsManager.CreateCreature(zombie2); + mObjectsManager.CreateCreature(zombie3); + mObjectsManager.CreateCreature(zombie4); + mObjectsManager.CreateCreature(zombie5); + mObjectsManager.CreateCreature(zombieToGo); + mObjectsManager.CreateCreature(knight); + mObjectsManager.CreateCreature(horse); + mObjectsManager.CreateCreature(meatball); +#endif + } + + public override bool HandleKeyEvent(IKeyEvent keyEvent) + { + if (keyEvent.KeyState == KeyState.Down && keyEvent.Key == Keys.Escape) + mMenuActions.OpenPauseScreen(); + if (keyEvent.KeyState == KeyState.Down && keyEvent.Key == Keys.F5) + { + Rectangle cameraRectangle = mCameraManager.GetCamera().ScreenRectangle; + mEffectsManager.PlayOnce(new SmokeBig(), cameraRectangle.Center, cameraRectangle.Size); + mObjectsManager.ExposeTheLiving(); + } + if (keyEvent.KeyState == KeyState.Down && keyEvent.Key == Keys.F6) + { + (mObjectsManager.PlayerCharacter as Necromancer)?.ChangeSex(); + mEffectsManager.PlayOnce(new SmokeSmall(), mObjectsManager.PlayerCharacter.Position.ToPoint(), new Point(256)); + } + if (keyEvent.KeyState == KeyState.Down && keyEvent.Key == Keys.F8) + { + mFogOfWarActivaded = !mFogOfWarActivaded; + } + + return true; + } + + /// + /// Updates the status of this object. + /// + /// a snapshot of the game time + public override void Update(GameTime gameTime) + { +#if DEBUG +#else + try + { +#endif + if (mObjectsManager.Boss != null && mObjectsManager.Boss.IsDead) + mAchievementsAndStatistics.mKillKing = true; + if (mObjectsManager.Prince != null && mObjectsManager.Prince.IsDead) + mAchievementsAndStatistics.mKillPrince = true; + mObjectsManager.Update(gameTime, mRightButtonPressed, mRightButtonPosition, mCameraManager.GetCamera()); + mCameraManager.Update(mObjectsManager.PlayerCharacter); + mEffectsManager.Update(gameTime); + mAiPlayer.Update(gameTime); + + // Call for Transformations + mTransformation.Transform(); + + // Check whether creature is in Necromancers Radius + mSelection.UpdateSelection(); + + // Update for FogOfWar. + for (int i = mFogCounter; i < mObjectsManager.UndeadCreatures.Count; i += 30) + { + mFog.Update(mObjectsManager.UndeadCreatures[i]); + } + if (mFogCounter < 30) + mFogCounter++; + else + mFogCounter = 0; + +#if DEBUG +#else + } + catch (System.Exception e) + { + System.Console.WriteLine(e.Message); + } +#endif + } + + /// + /// Draws this object using the given sprite batch. + /// + /// a snapshot of the game time + /// the sprite batch to use for drawing + /// this object + public override void Draw(GameTime gameTime, SpriteBatch spriteBatch) + { + mGraphicsDeviceManager.GraphicsDevice.Clear(Color.Black); + spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, + null, null, null, null, mCameraManager.GetCamera().Transform); + mMapManager.DrawFloor(spriteBatch, mCameraManager.GetCamera()); + mObjectsManager.Draw(spriteBatch, mCameraManager.GetCamera()); + mTransformation.DrawNecroArea(spriteBatch); + mEffectsManager.Draw(spriteBatch); + // Draws the selection rectangle when left mouse button is pressed. + if (mLeftButtonPressed) + mSelection.Draw(spriteBatch, mInitialClickPosition + mCameraManager.GetCamera().Location.ToPoint(), + Mouse.GetState().Position + mCameraManager.GetCamera().Location.ToPoint()); + if (mFogOfWarActivaded) mFog.DrawFog(spriteBatch); + if (mOptionsManager.Options.DebugMode == DebugMode.Full) + { + mMapManager.DrawPathfindingGrid(spriteBatch, mCameraManager.GetCamera()); + mObjectsManager.DrawQuadtree(spriteBatch); + DrawLastSelection(spriteBatch, mSelection.LastSelection); + } + spriteBatch.End(); + } + + private void DrawLastSelection(SpriteBatch spriteBatch, Rectangle selection) + { + spriteBatch.Draw(mOnePixelTexture, selection, new Color(Color.Black, 100)); + } + + public void SetFog(List fog) + { + mFog.SetFog(fog); + } + + public List GetFog() + { + return mFog.GetFog(); + } + + public void SetAiState(AiState state) + { + mAiPlayer.State = state; + } + + public AiState GetAiState() + { + return mAiPlayer.State; + } + } +} diff --git a/V3/Screens/HudScreen.cs b/V3/Screens/HudScreen.cs new file mode 100644 index 0000000..123ba8a --- /dev/null +++ b/V3/Screens/HudScreen.cs @@ -0,0 +1,349 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using Ninject; +using System.Collections.Generic; +using V3.Data; +using V3.Camera; +using V3.Input; +using V3.Map; +using V3.Objects; +using V3.Widgets; + +namespace V3.Screens +{ + /// + /// Creates a new HUD screen. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class HudScreen : AbstractScreen, IInitializable + { + private readonly MenuActions mMenuActions; + private readonly GraphicsDeviceManager mGraphicsDeviceManager; + private readonly ContentManager mContentManager; + private readonly WidgetFactory mWidgetFactory; + private readonly IOptionsManager mOptionsManager; + private readonly CameraManager mCameraManager; + private readonly IMapManager mMapManager; + private readonly IObjectsManager mObjectsManager; + private AchievementsAndStatistics mAchievementsAndStatistics; + + private KeyboardState mCurrentState; + private KeyboardState mPreviousState; + private SpriteFont mFont; + + private List