games/dino: binary size optimization (fix #537) (#632)
Build system / Build (en_US) (push) Successful in 3m8s
Build system / Build (es_ES) (push) Successful in 3m7s
Build system / Build (ru_RU) (push) Successful in 3m9s
Build system / Publish Images (push) Successful in 2m29s

- Size (fit into 8192 bytes or 16 IMG sectors):
  - Drop `ulist` in favor of static arrays
  - Dropping `malloc`/`free`/`exit`; `sprintf`, `pow`, `strlen` and 64-bit division no longer pull in libc and libtcc1
  - Dead code removed

- Rendering:
  - libimg dropped. `png2h.py` turns the original PNG into a palette-indexed atlas; the blit writes a 32bpp buffer, sysfn 65 puts it on screen - the same call `img_draw` made. No runtime PNG decode, output pixel-identical. The buffer ends at the ground line: 18% fewer pixels per frame

- Bugs fixed:
  - Every fourth pterodactyl was invisible and unhittable: `getRandomNumber` is inclusive, so `yPosArr[3]` read the next field (999) and the bird spawned off-screen
  - Releasing the jump key never shortened the first jump: gated on a flag set only after the intro; Chrome gates on the loop being scheduled
  - Flap rate `1000/6` truncated to 166, `minSpeed` 8.5 to 8 - birds came earlier than in Chrome
  - Hardcoded caption height clipped the window on every non-default skin
  - A maximum jump left the buffer and cut off the dino's head; the playfield is centered now
  - Obstacles and clouds leaked: nodes were freed, their data never

- Localization:
  - Caption localized to EN/RU/ES via `CONFIG_LANG`, fits every skin in the tree

Reviewed-on: #632
Reviewed-by: Kiril Lipatov <lipatov.kiril@gmail.com>
Reviewed-by: Ivan B <1+dunkaist@noreply.localhost>
This commit was merged in pull request #632.
This commit is contained in:
2026-08-14 13:51:14 +00:00
parent 647f35ea10
commit aa8913ea33
31 changed files with 456 additions and 1098 deletions
+1
View File
@@ -0,0 +1 @@
DINO
+1 -2
View File
@@ -8,10 +8,9 @@ KPACK = kpack
SRC = $(wildcard *.c)
FLAGS= -B$(KTCC_DIR)/bin -I $(KLIBC)/include -Wall# -stack=20480
LIBS = -limg
all: $(SRC)
$(KTCC) $(FLAGS) $(SRC) $(LIBS) -o $(NAME)
$(KTCC) $(FLAGS) $(SRC) -o $(NAME)
# $(KPACK) $(NAME)
clean:
+9 -4
View File
@@ -5,6 +5,14 @@ then
end
tup.include(HELPERDIR .. "/use_tcc.lua")
if tup.getconfig("LANG") == "ru_RU"
then C_LANG = "LANG_RUS"
elseif tup.getconfig("LANG") == "es_ES"
then C_LANG = "LANG_SPA"
else C_LANG = "LANG_ENG" -- this includes default case without config
end
CFLAGS = CFLAGS .. " -D" .. C_LANG
SRCS = {
"cloud.c",
"game_over_panel.c",
@@ -16,10 +24,7 @@ SRCS = {
"graphics.c",
"horizon_line.c",
"misc.c",
"runner.c",
"ulist.c"
"runner.c"
}
LIBS = " -limg"
link_tcc(SRCS, "dino");
+3 -7
View File
@@ -1,9 +1,7 @@
#include "cloud.h"
void cloudInit(Cloud* cloud, int w) {
cloud->width = w;
cloud->xPos = w;
cloud->yPos = 0;
void cloudInit(Cloud* cloud) {
cloud->xPos = DEFAULT_WIDTH;
cloud->remove = false;
cloud->cloudGap = getRandomNumber(CLOUD_MIN_GAP, CLOUD_MAX_GAP);
@@ -12,11 +10,10 @@ void cloudInit(Cloud* cloud, int w) {
}
void cloudDraw(const Cloud* cloud) {
graphicsBlitAtlasImage(ATLAS_CLOUD_X, ATLAS_CLOUD_Y, cloud->xPos, cloud->yPos, CLOUD_WIDTH, CLOUD_HEIGHT, false);
graphicsBlitAtlasImage(ATLAS_CLOUD_X, ATLAS_CLOUD_Y, cloud->xPos, cloud->yPos, CLOUD_WIDTH, CLOUD_HEIGHT);
}
void cloudUpdate(Cloud* cloud, double speed) {
// printf("cloudUpdate(., %f)\n", speed);
if (!cloud->remove) {
cloud->xPos -= (int)ceil(speed);
cloudDraw(cloud);
@@ -31,4 +28,3 @@ void cloudUpdate(Cloud* cloud, double speed) {
bool cloudIsVisible(const Cloud* cloud) {
return cloud->xPos + CLOUD_WIDTH > 0;
}
+1 -2
View File
@@ -14,14 +14,13 @@
#define CLOUD_MIN_SKY_LEVEL 71
typedef struct {
int width;
int xPos;
int yPos;
bool remove;
int cloudGap;
} Cloud;
void cloudInit(Cloud* cloud, int w);
void cloudInit(Cloud* cloud);
void cloudDraw(const Cloud* cloud);
void cloudUpdate(Cloud* cloud, double speed);
bool cloudIsVisible(const Cloud* cloud);
+5 -4
View File
@@ -1,11 +1,12 @@
#ifndef COLLISIONBOX_H
#define COLLISIONBOX_H
// All box coordinates fit in a byte (max value is 58)
typedef struct {
int x;
int y;
int width;
int height;
signed char x;
signed char y;
signed char width;
signed char height;
} CollisionBox;
#endif
+17 -2
View File
@@ -3,17 +3,32 @@
#define DEFAULT_WIDTH 600
#define DEFAULT_HEIGHT 200
#define GAME_HEIGHT 150
#define GAME_BOTTOM_PAD 10
#define GAME_Y_OFFSET ((DEFAULT_HEIGHT - GAME_HEIGHT) / 2)
#define BUFFER_HEIGHT (GAME_Y_OFFSET + GAME_HEIGHT - GAME_BOTTOM_PAD)
#define FPS 60
#define FRAME_TIME 30 // sysfn 5 sleeps in 10 ms steps
#define DELTA_MS_DEFAULT 20
#define WINDOW_TITLE "DINO. Jump: UP/SPACE Duck: DOWN Restart: jump or ENTER"
// The leading \3 tells the kernel the caption is UTF-8 (see gui/window.inc)
#ifdef LANG_RUS
#define WINDOW_TITLE "\3DINO [ПРЫЖОК-ВВЕРХ/ПРОБЕЛ ПРИСЕД-ВНИЗ РЕСТАРТ-ПРЫЖОК/ВВОД]"
#elif defined LANG_SPA
#define WINDOW_TITLE "\3DINO [SALTO-ARRIBA/ESPACIO AGACHADA-ABAJO REINICIO-SALTO/ENTER]"
#else
#define WINDOW_TITLE "\3DINO [JUMP-UP/SPACE DUCK-DOWN RESTART-JUMP/ENTER]"
#endif
// #define DBG
#ifdef DBG
#include <stdio.h>
#define dbg_printf(...) debug_printf(__VA_ARGS__)
#else
#else
#define dbg_printf(...)
#endif
+11 -35
View File
@@ -2,55 +2,32 @@
DistanceMeter distanceMeter;
void distanceMeterInit(int w) {
distanceMeter.x = 0;
distanceMeter.y = 5;
distanceMeter.currentDistance = 0;
distanceMeter.maxScore = 0;
distanceMeter.achievement = false;
distanceMeter.flashTimer = 0;
distanceMeter.flashIterations = 0;
distanceMeter.invertTrigger = false;
void distanceMeterInit() {
// in BSS: everything not set here starts at zero
distanceMeter.maxScore = 99999; // 10^DM_MAX_DISTANCE_UNITS - 1
distanceMeter.maxScoreUnits = DM_MAX_DISTANCE_UNITS;
distanceMeterCalcXPos(w);
for (int i = 0; i < distanceMeter.maxScoreUnits; i++) {
distanceMeterDraw(i, 0, false);
}
distanceMeter.maxScore = (int)pow(10, distanceMeter.maxScoreUnits) - 1;
distanceMeter.digits[0] = '\0';
distanceMeter.highScore[0] = '\0';
}
void distanceMeterCalcXPos(int w) {
distanceMeter.x = w - (DM_DEST_WIDTH * (distanceMeter.maxScoreUnits + 1));
}
void distanceMeterDraw(int digitPos, int value, bool opt_highscore) {
int dx, dy;
int dx = DM_X;
if (opt_highscore) {
dx = distanceMeter.x - (distanceMeter.maxScoreUnits * 2) * DM_WIDTH;
dy = distanceMeter.y;
dx -= (distanceMeter.maxScoreUnits * 2) * DM_WIDTH;
}
else {
dx = distanceMeter.x;
dy = distanceMeter.y;
}
//printf("%d %d %d %d %d %d\n", digitPos, value, opt_highscore, dx, dy, DM_WIDTH * value + ATLAS_TEXT_SPRITE_X);
graphicsBlitAtlasImage(
DM_WIDTH * value + ATLAS_TEXT_SPRITE_X,
0 + ATLAS_TEXT_SPRITE_Y,
digitPos * DM_DEST_WIDTH + dx,
distanceMeter.y + dy,
DM_Y * 2, // chrome translates by y and then draws at targetY == y
DM_WIDTH,
DM_HEIGHT,
false
DM_HEIGHT
);
}
void distanceMeterDrawHighScore() {
// TODO canvasCtx.globalAlpha = .8;
for (int i = (int)strlen(distanceMeter.highScore) - 1; i >= 0; i--) {
for (int i = distanceMeter.highScoreLen - 1; i >= 0; i--) {
distanceMeterDraw(i, distanceMeter.highScore[i] > 12 ? distanceMeter.highScore[i] - '0' : distanceMeter.highScore[i], true);
}
}
@@ -61,6 +38,7 @@ void distanceMeterSetHighScore(int _distance) {
distanceMeter.highScore[1] = 11;
distanceMeter.highScore[2] = 12;
intToStr(distance, distanceMeter.maxScoreUnits, distanceMeter.highScore + 3);
distanceMeter.highScoreLen = 3 + distanceMeter.maxScoreUnits;
}
void distanceMeterReset() {
@@ -69,7 +47,8 @@ void distanceMeterReset() {
}
int distanceMeterGetActualDistance(int distance) {
return distance ? (int)round(distance * DM_COEFFICIENT) : 0;
// round(distance * 0.025); 0.025 == 1/40
return (distance + 20) / 40;
}
bool distanceMeterUpdate(int deltaTime, int _distance) {
@@ -83,9 +62,6 @@ bool distanceMeterUpdate(int deltaTime, int _distance) {
distanceMeter.maxScoreUnits++;
distanceMeter.maxScore = distanceMeter.maxScore * 10 + 9;
}
// else {
// NOTE this.distance was in original but i didsnt see any usage of this field
// }
if (distance > 0) {
// Acheivement unlocked
+4 -9
View File
@@ -2,38 +2,33 @@
#define DISTANCE_METER_H
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include "graphics.h"
#include "misc.h"
#define DM_MAX_DISTANCE_UNITS 5
#define DM_ACHIEVEMENT_DISTANCE 100
#define DM_COEFFICIENT 0.025
#define DM_FLASH_DURATION 1000/4
#define DM_FLASH_ITERATIONS 3
#define DM_WIDTH 10
#define DM_HEIGHT 13
#define DM_DEST_WIDTH 11
#define DM_X (DEFAULT_WIDTH - DM_DEST_WIDTH * (DM_MAX_DISTANCE_UNITS + 1))
#define DM_Y 5
typedef struct {
int x;
int y;
int currentDistance;
int maxScore;
char digits[16];
char highScore[16];
int highScoreLen; // written length; strlen would drag in a libc import
bool achievement;
int flashTimer;
int flashIterations;
bool invertTrigger;
int maxScoreUnits;
} DistanceMeter;
extern DistanceMeter distanceMeter;
void distanceMeterInit(int w);
void distanceMeterCalcXPos(int w);
void distanceMeterInit();
void distanceMeterDraw(int digitPos, int value, bool opt_highscore);
int distanceMeterGetActualDistance(int distance);
bool distanceMeterUpdate(int deltaTime, int _distance);
+3 -16
View File
@@ -1,22 +1,9 @@
#include "game_over_panel.h"
GameOverPanel gameOverPanel;
void gameOverPanelInit(int width, int height) {
gameOverPanel.width = width;
gameOverPanel.height = height;
}
void gameOverPanelDraw() {
double centerX = gameOverPanel.width / 2;
int textTargetX = (int)round(centerX - (GOP_TEXT_WIDTH / 2));
int textTargetY = (int)round((gameOverPanel.height - 25) / 3);
int restartTargetX = centerX - (GOP_RESTART_WIDTH / 2);
int restartTargetY = gameOverPanel.height / 2;
// Game over text from sprite
// On the 600x150 canvas: round(300 - 191/2), round((150-25)/3), 300 - 36/2, 150/2
graphicsBlitAtlasImage(GOP_TEXT_X + ATLAS_TEXT_SPRITE_X, GOP_TEXT_Y + ATLAS_TEXT_SPRITE_Y,
textTargetX, textTargetY, GOP_TEXT_WIDTH, GOP_TEXT_HEIGHT, false);
// Restart button
205, 41, GOP_TEXT_WIDTH, GOP_TEXT_HEIGHT);
graphicsBlitAtlasImage(ATLAS_RESTART_X, ATLAS_RESTART_Y,
restartTargetX, restartTargetY, GOP_RESTART_WIDTH, GOP_RESTART_HEIGHT, false);
282, 75, GOP_RESTART_WIDTH, GOP_RESTART_HEIGHT);
}
-9
View File
@@ -1,7 +1,6 @@
#ifndef GAME_OVER_PANEL_H
#define GAME_OVER_PANEL_H
#include <math.h>
#include "graphics.h"
#define GOP_TEXT_X 0
@@ -11,14 +10,6 @@
#define GOP_RESTART_WIDTH 36
#define GOP_RESTART_HEIGHT 32
typedef struct {
int width;
int height;
} GameOverPanel;
extern GameOverPanel gameOverPanel;
void gameOverPanelInit(int width, int height);
void gameOverPanelDraw();
#endif
+27 -47
View File
@@ -1,39 +1,18 @@
#include "graphics.h"
#include "sprites.h"
#include <assert.h>
Image* screenImage;
static Image* spriteAtlas;
// 32bpp: sysfn 65 copies it as is, indices would cost a kernel lookup per pixel
static unsigned screenImage[DEFAULT_WIDTH * BUFFER_HEIGHT];
void graphicsInit() {
spriteAtlas = img_decode((void*)sprites100, sizeof(sprites100), 0);
*((uint8_t*)spriteAtlas->Palette + 3) = 0; // set black as transparent
// for (int i = 0; i < 16; i++) {
// dbg_printf("%x\n", *((uint8_t*)spriteAtlas->Palette + i));
// }
if (spriteAtlas->Type != IMAGE_BPP32) {
spriteAtlas = img_convert(spriteAtlas, NULL, IMAGE_BPP32, 0, 0);
if (!spriteAtlas) {
dbg_printf("spriteAtlas convert error\n");
exit(-1);
}
}
dbg_printf("spriteAtlas->Type = %d\n", spriteAtlas->Type);
screenImage = img_create(DEFAULT_WIDTH, DEFAULT_HEIGHT, IMAGE_BPP32);
}
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h) {
destY += GAME_Y_OFFSET; // playfield coordinates -> buffer coordinates
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center) {
// dbg_printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
int screen_width = (int)screenImage->Width;
int screen_height = (int)screenImage->Height;
if (destX >= screen_width) {
if (destX >= DEFAULT_WIDTH) {
return;
}
if (destY >= screen_height) {
if (destY >= BUFFER_HEIGHT) {
return;
}
@@ -42,8 +21,8 @@ void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w,
w = destX + w;
destX = 0;
}
if (destX + w > screen_width) {
w = screen_width - destX;
if (destX + w > DEFAULT_WIDTH) {
w = DEFAULT_WIDTH - destX;
}
if (destY < 0) {
@@ -51,37 +30,38 @@ void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w,
h = destY + h;
destY = 0;
}
if (destY + h > screen_height) {
h = screen_height - destY;
if (destY + h > BUFFER_HEIGHT) {
h = BUFFER_HEIGHT - destY;
}
if (w <= 0 || h <= 0) {
return;
}
//printf("start graphicsBlitAtlasImage ax = %d ay = %d dx = %d dy = %d w = %d h = %d %x %x\n\n", atlasX, atlasY, destX, destY, w, h, screenImage, spriteAtlas);
img_blend(screenImage, spriteAtlas, destX, destY, atlasX, atlasY, w, h);
// dbg_printf("end graphicsBlitAtlasImage\n\n");
const unsigned char* src = SPRITE_ATLAS + atlasY * ATLAS_WIDTH + atlasX;
unsigned* dst = screenImage + destY * DEFAULT_WIDTH + destX;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
unsigned char idx = src[x];
if (idx)
dst[x] = DINO_PALETTE[idx];
}
src += ATLAS_WIDTH;
dst += DEFAULT_WIDTH;
}
}
void graphicsFillBackground(unsigned r, unsigned g, unsigned b) {
img_fill_color(screenImage, screenImage->Width, screenImage->Height, (0xFF << 24) | (r << 16) | (g << 8) | b);
void graphicsFillBackground(void) {
unsigned* p = screenImage;
for (int i = DEFAULT_WIDTH * BUFFER_HEIGHT; i; --i)
*p++ = BACKGROUND_COLOR;
}
void graphicsRender() {
// don't redraw window on each frame. redraw window only when redraw event (called when widow moved e.g.)
img_draw(screenImage, 5, 24, screenImage->Width, screenImage->Height, 0, 0);
ksys_draw_bitmap_palette(screenImage, 0, 0, DEFAULT_WIDTH, BUFFER_HEIGHT, 32, 0, 0);
}
void graphicsDelay(int ms) {
// dbg_printf("ms = %d\n", ms);
_ksys_delay(ms/10 ? ms/10 : 2);
}
void graphicsDestroy() {
img_destroy(screenImage);
img_destroy(spriteAtlas);
_ksys_delay((ms + 9) / 10);
}
+4 -14
View File
@@ -1,12 +1,7 @@
#ifndef GRAPHICS_H
#define GRAPHICS_H
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/ksys.h>
#include <clayer/libimg.h>
#include "config.h"
@@ -18,8 +13,6 @@
#define ATLAS_CLOUD_Y 2
#define ATLAS_HORIZON_X 2
#define ATLAS_HORIZON_Y 54
#define ATLAS_MOON_X 484
#define ATLAS_MOON_Y 2
#define ATLAS_PTERODACTYL_X 134
#define ATLAS_PTERODACTYL_Y 2
#define ATLAS_RESTART_X 2
@@ -28,16 +21,13 @@
#define ATLAS_TEXT_SPRITE_Y 2
#define ATLAS_TREX_X 848
#define ATLAS_TREX_Y 2
#define ATLAS_STAR_X 645
#define ATLAS_STAR_Y 2
extern Image* screenImage;
#define WINDOW_BORDER 5 // window skin border
#define BACKGROUND_COLOR 0xF7F7F7
void graphicsInit();
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h, bool center);
void graphicsFillBackground(unsigned r, unsigned g, unsigned b);
void graphicsBlitAtlasImage(int atlasX, int atlasY, int destX, int destY, int w, int h);
void graphicsFillBackground(void);
void graphicsRender();
void graphicsDelay(int ms);
void graphicsDestroy();
#endif
+55 -77
View File
@@ -2,25 +2,15 @@
Horizon horizon;
void horizonInit(int dim_width, double gapCoefficient) {
horizon.dim_width = dim_width;
horizon.gapCoefficient = gapCoefficient;
horizon.obstacles = ulist_create();
horizon.obstacleHistory = ulist_create();
horizon.clouds = ulist_create();
void horizonInit() {
// in BSS: the counts start at zero
horizonAddCloud();
horizonLineInit();
}
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode) {
//horizon.runningTime += deltaTime;
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles) {
horizonLineUpdate(deltaTime, currentSpeed);
// if (currentSpeed != currentSpeed) {
// currentSpeed = 6.0;
// }
// horizon.nightMode.update(showNightMode);
horizonUpdateClouds(deltaTime, currentSpeed);
if (updateObstacles) {
horizonUpdateObstacles(deltaTime, currentSpeed);
@@ -28,32 +18,29 @@ void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, boo
}
void horizonUpdateClouds(int deltaTime, double speed) {
//printf("horizonUpdateClouds()\n");
double cloudSpeed = HORIZON_BG_CLOUD_SPEED / 1000 * deltaTime * speed;
int numClouds = ulist_size(horizon.clouds);
//printf("horizonUpdateClouds() %d\n", numClouds);
if (numClouds) {
Node *cloudNode = horizon.clouds->tail;
while (cloudNode != NULL) {
cloudUpdate(cloudNode->data, cloudSpeed);
cloudNode = cloudNode->prev;
if (horizon.cloudCount) {
// Update (and draw) the newest cloud first
for (int i = horizon.cloudCount - 1; i >= 0; i--) {
cloudUpdate(&horizon.clouds[i], cloudSpeed);
}
Cloud *lastCloud = horizon.clouds->tail->data;
// Check for adding a new cloud
if (numClouds < HORIZON_MAX_CLOUDS && (horizon.dim_width - lastCloud->xPos) > lastCloud->cloudGap && HORIZON_CLOUD_FREQUENCY > (double)rand()/RAND_MAX) {
Cloud *lastCloud = &horizon.clouds[horizon.cloudCount - 1];
// Check for adding a new cloud (frequency 0.5)
if (horizon.cloudCount < HORIZON_MAX_CLOUDS && (DEFAULT_WIDTH - lastCloud->xPos) > lastCloud->cloudGap && rand() <= RAND_MAX / 2) {
horizonAddCloud();
}
// Remove expired clouds
cloudNode = horizon.clouds->head;
while (cloudNode != NULL) {
Node* cloudNodeNext = cloudNode->next;
Cloud* c = cloudNode->data;
if (c->remove) {
ulist_remove(horizon.clouds, cloudNode);
int kept = 0;
for (int i = 0; i < horizon.cloudCount; i++) {
if (!horizon.clouds[i].remove) {
if (kept != i) {
horizon.clouds[kept] = horizon.clouds[i];
}
kept++;
}
cloudNode = cloudNodeNext;
}
horizon.cloudCount = kept;
}
else {
horizonAddCloud();
@@ -61,28 +48,25 @@ void horizonUpdateClouds(int deltaTime, double speed) {
}
void horizonUpdateObstacles(int deltaTime, double currentSpeed) {
//printf("horizonUpdateObstacles()\n");
// Obstacles, move to Horizon layer
Node* obNode = horizon.obstacles->head;
while (obNode != NULL) {
Node* obNodeNext = obNode->next;
Obstacle* ob = obNode->data;
obstacleUpdate(ob, deltaTime, currentSpeed);
// Clean up existing obstacles
if (ob->remove) {
//ulist_remove(horizon.obstacles, obNode);
//ulist_print(horizon.obstacles);
ulist_remove_front(horizon.obstacles);
//ulist_print(horizon.obstacles);
//puts("");
}
obNode = obNodeNext;
for (int i = 0; i < horizon.obstacleCount; i++) {
obstacleUpdate(&horizon.obstacles[i], deltaTime, currentSpeed);
}
// Clean up removed obstacles
int kept = 0;
for (int i = 0; i < horizon.obstacleCount; i++) {
if (!horizon.obstacles[i].remove) {
if (kept != i) {
horizon.obstacles[kept] = horizon.obstacles[i];
}
kept++;
}
}
horizon.obstacleCount = kept;
if (ulist_size(horizon.obstacles) > 0) {
Obstacle *lastObstacle = horizon.obstacles->tail->data;
if (horizon.obstacleCount > 0) {
Obstacle *lastObstacle = &horizon.obstacles[horizon.obstacleCount - 1];
if (lastObstacle && !lastObstacle->followingObstacleCreated && obstacleIsVisible(lastObstacle) && (lastObstacle->xPos + lastObstacle->width + lastObstacle->gap) < horizon.dim_width) {
if (!lastObstacle->followingObstacleCreated && obstacleIsVisible(lastObstacle) && (lastObstacle->xPos + lastObstacle->width + lastObstacle->gap) < DEFAULT_WIDTH) {
horizonAddNewObstacle(currentSpeed);
lastObstacle->followingObstacleCreated = true;
}
@@ -94,6 +78,9 @@ void horizonUpdateObstacles(int deltaTime, double currentSpeed) {
}
void horizonAddNewObstacle(double currentSpeed) {
if (horizon.obstacleCount >= HORIZON_MAX_OBSTACLES) {
return; // no room; retried on a later frame
}
int obstacleTypeIndex = getRandomNumber(0, sizeof(obstacleTypeConfigs)/sizeof(ObstacleTypeConfig) - 1);
ObstacleTypeConfig *otc = &obstacleTypeConfigs[obstacleTypeIndex];
@@ -103,45 +90,36 @@ void horizonAddNewObstacle(double currentSpeed) {
horizonAddNewObstacle(currentSpeed);
}
else {
Obstacle* ob = malloc(sizeof(Obstacle));
obstacleInit(ob, otc, horizon.dim_width, horizon.gapCoefficient, currentSpeed, otc->width);
ulist_push_back(horizon.obstacles, ob);
ulist_push_front(horizon.obstacleHistory, &(otc->type));
if (ulist_size(horizon.obstacleHistory) > 1) {
ulist_splice(horizon.obstacleHistory, RUNNER_MAX_OBSTACLE_DUPLICATION);
obstacleInit(&horizon.obstacles[horizon.obstacleCount], otc, currentSpeed, otc->width);
horizon.obstacleCount++;
// Record the type, newest first, keeping the last few entries
for (int i = HORIZON_MAX_OBSTACLE_DUPLICATION - 1; i > 0; i--) {
horizon.obstacleHistory[i] = horizon.obstacleHistory[i - 1];
}
horizon.obstacleHistory[0] = otc->type;
if (horizon.obstacleHistoryCount < HORIZON_MAX_OBSTACLE_DUPLICATION) {
horizon.obstacleHistoryCount++;
}
}
}
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType) {
//printf("horizonDuplicateObstacleCheck(%d)\n", nextObstacleType);
int duplicateCount = 0;
Node* ohNode = horizon.obstacleHistory->head;
while (ohNode != NULL) {
//printf("%d\n", *(int*)ohNode->data);
duplicateCount = *(int*)ohNode->data == nextObstacleType ? duplicateCount + 1 : 0;
ohNode = ohNode->next;
for (int i = 0; i < horizon.obstacleHistoryCount; i++) {
duplicateCount = horizon.obstacleHistory[i] == nextObstacleType ? duplicateCount + 1 : 0;
}
//printf("duplicateCount = %d\n\n", duplicateCount);
return duplicateCount >= RUNNER_MAX_OBSTACLE_DUPLICATION;
return duplicateCount >= HORIZON_MAX_OBSTACLE_DUPLICATION;
}
void horizonReset() {
// printf("horizonReset() !!\n");
ulist_destroy(horizon.obstacles);
horizon.obstacles = ulist_create();
horizon.obstacleCount = 0;
horizonLineReset();
}
//void horizonResize(int width, int height) {
//
//}
void horizonAddCloud() {
Cloud* c = malloc(sizeof(Cloud));
cloudInit(c, horizon.dim_width);
//printf("horizonAddCloud() %d -> ", ulist_size(horizon.obstacles));
ulist_push_back(horizon.clouds, c);
//printf("%d\n", ulist_size(horizon.obstacles));
if (horizon.cloudCount >= HORIZON_MAX_CLOUDS) {
return;
}
cloudInit(&horizon.clouds[horizon.cloudCount]);
horizon.cloudCount++;
}
+11 -15
View File
@@ -1,41 +1,37 @@
#ifndef HORIZON_H
#define HORIZON_H
#include <math.h>
#include <stdbool.h>
#include "obstacle.h"
#include "cloud.h"
#include "horizon_line.h"
#include "runner.h"
#include "graphics.h"
#include "ulist.h"
#define HORIZON_BG_CLOUD_SPEED 0.2
#define HORIZON_BUMPY_THRESHOLD 0.3
#define HORIZON_CLOUD_FREQUENCY 0.5
#define HORIZON_HORIZON_HEIGHT 16
#define HORIZON_MAX_CLOUDS 6
#define HORIZON_MAX_OBSTACLES 8 // ~5 fit on screen at the smallest gaps
#define HORIZON_MAX_OBSTACLE_DUPLICATION 2
typedef struct {
int dim_width;
double gapCoefficient;
Ulist* obstacles;
Ulist* obstacleHistory;
// nightMode
Ulist* clouds;
Obstacle obstacles[HORIZON_MAX_OBSTACLES];
int obstacleCount;
ObstacleType obstacleHistory[HORIZON_MAX_OBSTACLE_DUPLICATION];
int obstacleHistoryCount;
Cloud clouds[HORIZON_MAX_CLOUDS];
int cloudCount;
} Horizon;
extern Horizon horizon;
void horizonInit(int dim_width, double gapCoefficient);
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles, bool showNightMode);
void horizonInit();
void horizonUpdate(int deltaTime, double currentSpeed, bool updateObstacles);
void horizonUpdateClouds(int deltaTime, double speed);
void horizonUpdateObstacles(int deltaTime, double currentSpeed);
//void horizonRemoveFirstObstacle();
void horizonAddNewObstacle(double currentSpeed);
bool horizonDuplicateObstacleCheck(ObstacleType nextObstacleType);
void horizonReset();
//void horizonResize(int width, int height);
void horizonAddCloud();
#endif
+14 -18
View File
@@ -3,25 +3,21 @@
HorizonLine horizonLine;
void horizonLineInit() {
horizonLine.width = HORIZON_LINE_WIDTH;
horizonLine.height = HORIZON_LINE_HEIGHT;
// in BSS: xPos[0] starts at zero
horizonLine.sourceXPos[0] = ATLAS_HORIZON_X;
horizonLine.sourceXPos[1] = ATLAS_HORIZON_X + horizonLine.width;
horizonLine.bumpThreshold = 0.5;
horizonLine.xPos[0] = 0;
horizonLine.xPos[1] = horizonLine.width;
horizonLine.yPos = HORIZON_LINE_YPOS;
horizonLine.sourceXPos[1] = ATLAS_HORIZON_X + HORIZON_LINE_WIDTH;
horizonLine.xPos[1] = HORIZON_LINE_WIDTH;
horizonLineDraw();
}
void horizonLineDraw() {
//printf("horizonLineDraw(); xPos[0] = %d, xPos[1] = %d, yPos = %d, width = %d, height = %d\n", horizonLine.xPos[0], horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height);
graphicsBlitAtlasImage(horizonLine.sourceXPos[0], ATLAS_HORIZON_Y, horizonLine.xPos[0], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
graphicsBlitAtlasImage(horizonLine.sourceXPos[1], ATLAS_HORIZON_Y, horizonLine.xPos[1], horizonLine.yPos, horizonLine.width, horizonLine.height, false);
graphicsBlitAtlasImage(horizonLine.sourceXPos[0], ATLAS_HORIZON_Y, horizonLine.xPos[0], HORIZON_LINE_YPOS, HORIZON_LINE_WIDTH, HORIZON_LINE_HEIGHT);
graphicsBlitAtlasImage(horizonLine.sourceXPos[1], ATLAS_HORIZON_Y, horizonLine.xPos[1], HORIZON_LINE_YPOS, HORIZON_LINE_WIDTH, HORIZON_LINE_HEIGHT);
}
int horizonLineGetRandomType() {
return (double)rand() / RAND_MAX > horizonLine.bumpThreshold ? horizonLine.width : 0;
// bump threshold 0.5
return rand() > RAND_MAX / 2 ? HORIZON_LINE_WIDTH : 0;
}
void horizonLineUpdateXPos(int pos, int increment) {
@@ -29,28 +25,28 @@ void horizonLineUpdateXPos(int pos, int increment) {
int line2 = pos == 0 ? 1 : 0;
horizonLine.xPos[line1] -= increment;
horizonLine.xPos[line2] = horizonLine.xPos[line1] + horizonLine.width;
horizonLine.xPos[line2] = horizonLine.xPos[line1] + HORIZON_LINE_WIDTH;
if (horizonLine.xPos[line1] <= -horizonLine.width) {
horizonLine.xPos[line1] += horizonLine.width * 2;
horizonLine.xPos[line2] = horizonLine.xPos[line1] - horizonLine.width;
if (horizonLine.xPos[line1] <= -HORIZON_LINE_WIDTH) {
horizonLine.xPos[line1] += HORIZON_LINE_WIDTH * 2;
horizonLine.xPos[line2] = horizonLine.xPos[line1] - HORIZON_LINE_WIDTH;
horizonLine.sourceXPos[line1] = horizonLineGetRandomType() + ATLAS_HORIZON_X;
}
}
void horizonLineUpdate(int deltaTime, double speed) {
int increment = floor(speed * (FPS / 1000.0) * deltaTime);
// value is always positive, so truncation == floor
int increment = speed * (FPS / 1000.0) * deltaTime;
if (horizonLine.xPos[0] <= 0) {
horizonLineUpdateXPos(0, increment);
}
else {
horizonLineUpdateXPos(1, increment);
}
// asm_inline("int $3");
horizonLineDraw();
}
void horizonLineReset() {
horizonLine.xPos[0] = 0;
horizonLine.xPos[1] = horizonLine.width;
horizonLine.xPos[1] = HORIZON_LINE_WIDTH;
}
-7
View File
@@ -1,10 +1,7 @@
#ifndef HORIZON_LINE_H
#define HORIZON_LINE_H
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "config.h"
#include "graphics.h"
@@ -13,12 +10,8 @@
#define HORIZON_LINE_YPOS 127
typedef struct {
int width;
int height;
int sourceXPos[2];
int xPos[2];
int yPos;
double bumpThreshold;
} HorizonLine;
extern HorizonLine horizonLine;
+17 -69
View File
@@ -1,9 +1,5 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/ksys.h>
@@ -16,121 +12,73 @@
#include "trex.h"
#include "runner.h"
static uint8_t keyboard_layout[128];
int main(int argc, char* args[]) {
srand((unsigned int)time(NULL)); // Seed the random number generator
srand((unsigned int)_ksys_get_ns_count()); // Seed the random number generator
ksys_pos_t win_pos = _ksys_screen_size();
win_pos.x /= 2;
win_pos.x -= DEFAULT_WIDTH/2;
win_pos.y /= 2;
win_pos.y -= DEFAULT_HEIGHT/2;
dbg_printf("wx = %d, wy = %d\n", win_pos.x, win_pos.y);
ksys_colors_table_t sys_color_table;
_ksys_get_system_colors(&sys_color_table);
_ksys_set_event_mask(0xC0000027); // !
_ksys_set_key_input_mode(KSYS_KEY_INPUT_MODE_SCANC);
_ksys_keyboard_layout(KSYS_KEYBOARD_LAYOUT_NORMAL, keyboard_layout);
graphicsInit();
runnerInit();
dbg_printf("dino started\n");
int ext_code = 0;
uint8_t old_mode = 0;
bool quit = false;
while (quit == false) {
for (;;) {
int frameStartTime = getTimeStamp();
//printf("frameStartTime = %d\n", frameStartTime);
uint32_t kos_event = _ksys_check_event();
switch (kos_event) {
switch (_ksys_check_event()) {
case KSYS_EVENT_BUTTON:
switch (_ksys_get_button()){
case 1:
quit = true;
break;
default:
break;
}
break;
_ksys_get_button();
_ksys_exit(); // the close button is the only one
case KSYS_EVENT_KEY:
{
ksys_oskey_t key = _ksys_get_key();
uint8_t scancode = key.code;
if (scancode == 0xE0 || scancode == 0xE1) {
ext_code = scancode;
unsigned char scancode = key.code;
if (scancode == 0xE0) {
ext_code = 0x100;
break;
}
if (ext_code == 0xE1 && (scancode & 0x7F) == 0x1D) {
break;
}
if (ext_code == 0xE1 && scancode == 0xC5) {
ext_code = 0;
break;
}
uint8_t code = keyboard_layout[scancode & 0x7F];
if (ext_code == 0xE0) {
code -= 96;
}
int code = (scancode & 0x7F) | ext_code;
ext_code = 0;
if (scancode < 128) { // KEYDOWN
//dbg_printf("Keydown: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
//dbg_printf("keydown c = %u\n", key.code);
runnerOnKeyDown(code);
} else { // KEYUP
//dbg_printf("Keyup: key = 0x%x, scancode = 0x%x, code = 0x%x (%u) state = 0x%x\n", key.val, scancode, code, code, key.state);
//dbg_printf("keyup c = %u\n", key.code);
runnerOnKeyUp(code);
}
}
break;
case KSYS_EVENT_REDRAW:
//dbg_printf("KSYS_EVENT_REDRAW\n");
_ksys_start_draw();
_ksys_create_window(win_pos.x, win_pos.y, screenImage->Width + 10, screenImage->Height + 29, WINDOW_TITLE, sys_color_table.work_area, 0x54); // 0x54. note: C = 1 !!
_ksys_create_window(
win_pos.x, win_pos.y,
DEFAULT_WIDTH + 2*WINDOW_BORDER,
DEFAULT_HEIGHT + _ksys_get_skin_height() + WINDOW_BORDER,
WINDOW_TITLE, BACKGROUND_COLOR, 0x34);
graphicsRender();
_ksys_end_draw();
break;
break;
default:
break;
}
if (runner.nextUpdateScheduled) {
//printf("runner update! %u\n", getTimeStamp());
//dbg_printf("runnerUpdate\n");
runnerUpdate();
}
else {
if (runner.skipUpdateNow) {
//printf("Skipped one update\n");
runner.nextUpdateScheduled = true;
runner.skipUpdateNow = false;
}
}
int frameTime = getTimeStamp() - frameStartTime;
if (frameTime < 0) {
frameTime = DELTA_MS_DEFAULT;
}
#define FRAME_TIME 20 //16
// dbg_printf("frameTime = %d\n", frameTime);
if (frameTime < FRAME_TIME) { // 1000ms/60frames = 16.(6)
// printf("frameTime = %d\n", frameTime);
if (runner.crashed) {
// dbg_printf("runner.timeAfterCrashedMs +=\n");
runner.timeAfterCrashedMs += FRAME_TIME - frameTime;
}
if (frameTime < FRAME_TIME) {
graphicsDelay(FRAME_TIME - frameTime);
}
}
graphicsDestroy();
return 0;
}
+13 -16
View File
@@ -4,25 +4,22 @@ int getRandomNumber(int _min, int _max) {
return rand() % (_max - _min + 1) + _min;
}
// Zero-padded decimal, keeps only the last ndigits (num is never negative here)
void intToStr(int num, int ndigits, char* result) {
char num_str[16]; // 16 more than enough for int
sprintf(num_str, "%d", num); // Convert num to a string
if (strlen(num_str) > ndigits) {
// Copy only the last ndigits to result
strcpy(result, num_str + strlen(num_str) - ndigits);
}
else {
// Pad the string with leading zeros until it reaches a length of ndigits
size_t z = ndigits - strlen(num_str);
for (size_t i = 0; i < z; i++) {
result[i] = '0';
}
strcpy(result + z, num_str);
result[ndigits] = '\0';
for (int i = ndigits - 1; i >= 0; i--) {
result[i] = '0' + num % 10;
num /= 10;
}
}
int getTimeStamp() { // in ms
uint64_t x = 0;
x = _ksys_get_ns_count();
return (x/1000000);
// Any long long here would link all of libtcc1
unsigned lo, hi;
// sysfn 26.10: nanosecond counter in edx:eax
asm_inline("int $0x40" : "=a"(lo), "=d"(hi) : "a"(26), "b"(10));
// low 32 bits of ns/1000000: (hi%d):lo divided by d always fits
hi %= 1000000;
asm_inline("divl %2" : "+a"(lo), "+d"(hi) : "r"(1000000u));
return lo;
}
+9 -2
View File
@@ -1,11 +1,18 @@
#ifndef MISC_H
#define MISC_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ksys.h>
// ktcc's ksys.h provides max as a macro, newlib's does not
#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif
#define GAME_RAND_MAX 0x7FFFFFFF
unsigned gameRand(void);
void gameSeed(unsigned seed);
int getRandomNumber(int _min, int _max);
void intToStr(int num, int ndigits, char* result);
int getTimeStamp();
+15 -17
View File
@@ -54,21 +54,20 @@ ObstacleTypeConfig obstacleTypeConfigs[3] = {
{.x = 10, .y = 8, .width = 6, .height = 9}
},
.numFrames = 2,
.frameRate = 1000 / 6,
.frameRate = 1000 / 6.,
.speedOffset = 0.8
}
};
int obstacleSpritePosX[3] = { ATLAS_CACTUS_SMALL_X, ATLAS_CACTUS_LARGE_X, ATLAS_PTERODACTYL_X};
int obstacleSpritePosY[3] = { ATLAS_CACTUS_SMALL_Y, ATLAS_CACTUS_LARGE_Y, ATLAS_PTERODACTYL_Y};
short obstacleSpritePosX[3] = { ATLAS_CACTUS_SMALL_X, ATLAS_CACTUS_LARGE_X, ATLAS_PTERODACTYL_X};
short obstacleSpritePosY[3] = { ATLAS_CACTUS_SMALL_Y, ATLAS_CACTUS_LARGE_Y, ATLAS_PTERODACTYL_Y};
void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset) {
void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, double speed, int opt_xOffset) {
ob->typeConfig = *otc;
ob->gapCoefficient = gapCoefficient;
ob->size = getRandomNumber(1, OBSTACLE_MAX_OBSTACLE_LENGTH);
ob->remove = false;
ob->xPos = dim_width + opt_xOffset;
ob->xPos = DEFAULT_WIDTH + opt_xOffset;
ob->yPos = 0;
// For animated obstacles
@@ -83,7 +82,8 @@ void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, int dim_width, do
ob->width = ob->typeConfig.width * ob->size;
if (ob->typeConfig.yPos == -1) {
ob->yPos = ob->typeConfig.yPosArr[getRandomNumber(0, ob->typeConfig.yPosArrSize)];
// getRandomNumber is inclusive on both ends
ob->yPos = ob->typeConfig.yPosArr[getRandomNumber(0, ob->typeConfig.yPosArrSize - 1)];
}
else {
ob->yPos = ob->typeConfig.yPos;
@@ -107,27 +107,25 @@ void obstacleInit(Obstacle* ob, const ObstacleTypeConfig *otc, int dim_width, do
// For obstacles that go at a different speed from the horizon
if (ob->typeConfig.speedOffset) {
ob->typeConfig.speedOffset = (double)rand() / RAND_MAX > 0.5 ? ob->typeConfig.speedOffset : -ob->typeConfig.speedOffset;
ob->typeConfig.speedOffset = rand() > RAND_MAX / 2 ? ob->typeConfig.speedOffset : -ob->typeConfig.speedOffset;
}
ob->gap = obstacleGetGap(ob, ob->gapCoefficient, speed);
ob->gap = obstacleGetGap(ob, speed);
}
void obstacleDraw(const Obstacle *ob) {
int sourceWidth = ob->typeConfig.width;
int sourceHeight = ob->typeConfig.height;
int sourceX = (sourceWidth * ob->size) * (0.5 * ((double)ob->size - 1)) + obstacleSpritePosX[ob->typeConfig.type];
int sourceX = sourceWidth * ob->size * (ob->size - 1) / 2 + obstacleSpritePosX[ob->typeConfig.type];
if (ob->currentFrame > 0) {
sourceX += sourceWidth*ob->currentFrame;
}
//dbg_printf("od ax=%u, ay=%u, dx=%u, dy=%u, w=%u, h=%u\n", sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight);
graphicsBlitAtlasImage(sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight, false);
graphicsBlitAtlasImage(sourceX, obstacleSpritePosY[ob->typeConfig.type], ob->xPos, ob->yPos, sourceWidth*ob->size, sourceHeight);
}
void obstacleUpdate(Obstacle *ob, int deltaTime, double speed) {
if (!ob->remove) {
double dx = floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
//dbg_printf("sp = %lf, ots = %lf, dx = %d, xpos = %d\n", speed, ob->typeConfig.speedOffset, (int)dx, ob->xPos - dx);
ob->xPos -= dx;//floor(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
// value is always positive, so truncation == floor
ob->xPos -= (int)(((speed + ob->typeConfig.speedOffset)*FPS/1000.)*deltaTime);
}
// Update frames
if (ob->typeConfig.numFrames > 1) {
@@ -143,8 +141,8 @@ void obstacleUpdate(Obstacle *ob, int deltaTime, double speed) {
}
}
int obstacleGetGap(const Obstacle *ob, double gapCoefficient, double speed) {
int minGap = round(ob->width * speed + ob->typeConfig.minGap * gapCoefficient);
int obstacleGetGap(const Obstacle *ob, double speed) {
int minGap = round(ob->width * speed + ob->typeConfig.minGap * OBSTACLE_GAP_COEFFICIENT);
int maxGap = round(minGap * OBSTACLE_MAX_GAP_COEFFICIENT);
return getRandomNumber(minGap, maxGap);
}
+20 -18
View File
@@ -12,6 +12,9 @@
// Coefficient for calculating the maximum gap
#define OBSTACLE_MAX_GAP_COEFFICIENT 1.5
// Coefficient for calculating the minimum gap
#define OBSTACLE_GAP_COEFFICIENT 0.6
// Maximum obstacle grouping count
#define OBSTACLE_MAX_OBSTACLE_LENGTH 3
@@ -21,36 +24,35 @@ typedef enum {
PTERODACTYL = 2
} ObstacleType;
extern int obstacleSpritePosX[3];
extern int obstacleSpritePosY[3];
extern short obstacleSpritePosX[3];
extern short obstacleSpritePosY[3];
// Every value fits in a short (the largest is 999)
typedef struct {
ObstacleType type;
int width;
int height;
int yPos;
int yPosArrSize;
int yPosArr[3]; // used if yPos is -1
int multipleSpeed;
int minGap;
int minSpeed;
int collisionBoxesCount;
short type; // ObstacleType
short width;
short height;
short yPos;
short yPosArrSize;
short yPosArr[3]; // used if yPos is -1
short multipleSpeed;
short minGap;
float minSpeed; // 8.5 for the pterodactyl: exact in float, must not truncate
short collisionBoxesCount;
CollisionBox collisionBoxes[5];
int numFrames;
double frameRate;
short numFrames;
float frameRate;
double speedOffset;
} ObstacleTypeConfig;
typedef struct {
ObstacleTypeConfig typeConfig;
double gapCoefficient;
int size;
bool remove;
int xPos;
int yPos;
int width;
int gap;
// double speedOffset;
int currentFrame;
int timer;
bool followingObstacleCreated;
@@ -58,10 +60,10 @@ typedef struct {
extern ObstacleTypeConfig obstacleTypeConfigs[3];
void obstacleInit(Obstacle *ob, const ObstacleTypeConfig *otc, int dim_width, double gapCoefficient, double speed, int opt_xOffset);
void obstacleInit(Obstacle *ob, const ObstacleTypeConfig *otc, double speed, int opt_xOffset);
void obstacleDraw(const Obstacle* ob);
void obstacleUpdate(Obstacle* ob, int deltaTime, double speed);
int obstacleGetGap(const Obstacle* ob, double gapCoefficient, double speed);
int obstacleGetGap(const Obstacle* ob, double speed);
bool obstacleIsVisible(const Obstacle* ob);
#endif
+57
View File
@@ -0,0 +1,57 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Atlas converter for the Dino game: PNG -> palette-indexed C header.
# The final binary is kpack-compressed, so the flat index array costs
# about the same on disk as any pre-compressed encoding would.
#
# Usage: python png2h.py sprites100.png sprites.h
import os
import sys
from PIL import Image
# Regions the game never draws (moon and stars: night mode is not implemented)
BLANK = [(482, 0, 654, 53)]
def main():
src, dst = sys.argv[1], sys.argv[2]
img = Image.open(src).convert("RGBA")
w, h = img.size
pixels = list(img.getdata())
opaque = [None if a == 0 else (r, g, b) for r, g, b, a in pixels]
for x0, y0, x1, y1 in BLANK:
for y in range(y0, y1 + 1):
for x in range(x0, x1 + 1):
opaque[y * w + x] = None
# Transparent -> 0, remaining colors by frequency -> 1..N
freq = {}
for c in opaque:
if c is not None:
freq[c] = freq.get(c, 0) + 1
colors = sorted(freq, key=freq.get, reverse=True)
index = {c: i + 1 for i, c in enumerate(colors)}
data = [0 if c is None else index[c] for c in opaque]
with open(dst, "w", newline="\n") as f:
f.write("// Generated by png2h.py from %s - do not edit\n" % os.path.basename(src))
f.write("#pragma once\n\n")
f.write("#define ATLAS_WIDTH %d\n" % w)
f.write("#define ATLAS_HEIGHT %d\n\n" % h)
f.write("// Index 0 is transparent\n")
f.write("static const unsigned DINO_PALETTE[%d] = {\n 0x00000000," % (len(colors) + 1))
for r, g, b in colors:
f.write(" 0x00%02X%02X%02X," % (r, g, b))
f.write("\n};\n\n")
f.write("static const unsigned char SPRITE_ATLAS[ATLAS_WIDTH * ATLAS_HEIGHT] = {\n")
for y in range(h):
row = data[y * w:(y + 1) * w]
f.write(" " + ",".join(str(v) for v in row) + ",\n")
f.write("};\n")
print(f"atlas {w}x{h}, {len(colors)} colors + transparent, {len(data)} bytes")
if __name__ == "__main__":
main()
+52 -170
View File
@@ -1,63 +1,32 @@
#include "runner.h"
int aaaaaaa[10000];
Runner runner;
int bbbbbb[10000];
void runnerInit() {
runner.distanceRan = 0;
runner.highestScore = 0;
runner.time = 0;
runner.msPerFrame = 1000.0 / FPS;
// in BSS: everything not set here starts at zero
runner.currentSpeed = RUNNER_SPEED;
runner.activated = false;
runner.playing = false;
runner.crashed = false;
runner.timeAfterCrashedMs = 0;
runner.paused = false;
runner.inverted = false;
runner.playingIntro = false;
runner.isRunning = false; // is running or game stopped
runner.invertTimer = 0;
runner.playCount = 0;
runner.nextUpdateScheduled = false;
runner.skipUpdateNow = false;
// TODO sound
// runnerLoadImages();
runnerAdjustDimensions();
// setSpeed
graphicsFillBackground(0xF7, 0xF7, 0xF7);
graphicsFillBackground();
gameOverPanelInit(runner.width, runner.height);
horizonInit(runner.width, RUNNER_GAP_COEFFICIENT);
distanceMeterInit(runner.width);
horizonInit();
distanceMeterInit();
trexInit();
// this.startListening();
runnerUpdate();
//window.addEventListener(Runner.events.RESIZE, this.debounceResize.bind(this));
}
void runnerAdjustDimensions() {
runner.width = DEFAULT_WIDTH;
runner.height = RUNNER_DEFAULT_HEIGHT;
// distance meter ...
static bool isJumpKey(int key) {
return key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2;
}
void runnerOnKeyDown(int key) {
if (!runner.crashed && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
if (!runner.crashed && isJumpKey(key)) {
if (!runner.playing) {
// this.loadSounds(); // TODO
runner.playing = true;
//printf("first jump! %u\n", getTimeStamp());
runnerUpdate();
runner.nextUpdateScheduled = false;
runner.skipUpdateNow = true;
}
// Play sound effect and jump on starting the game for the first time.
// Jump on starting the game for the first time.
if (!trex.jumping && !trex.ducking) {
// this.playSound(this.soundFx.BUTTON_PRESS); // TODO
trexStartJump(runner.currentSpeed);
}
}
@@ -66,7 +35,6 @@ void runnerOnKeyDown(int key) {
// Speed drop, activated only when jump key is not pressed.
trexSetSpeedDrop();
}
//else if (!trex.jumping &&!trex.ducking) {
else if (!trex.ducking) {
// Duck
trexSetDuck(true);
@@ -75,7 +43,7 @@ void runnerOnKeyDown(int key) {
}
void runnerOnKeyUp(int key) {
if (runner.isRunning && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
if (runner.playing && isJumpKey(key)) {
trexEndJump();
}
else if (key == RUNNER_KEYCODE_DUCK) {
@@ -83,45 +51,26 @@ void runnerOnKeyUp(int key) {
trexSetDuck(false);
}
else if (runner.crashed) {
// Check that enough time has elapsed before allowing jump key to restart.
int now = getTimeStamp();
int deltaTime = now - runner.time;
// if (deltaTime < 0) {
// deltaTime = DELTA_MS_DEFAULT;
// runner.time = 0;
// }
// dbg_printf(".now = %d .deltaTime = %d runner.time = %d\n", now, deltaTime, runner.time);
if (key == RUNNER_KEYCODE_RESTART || (runner.timeAfterCrashedMs >= RUNNER_GAMEOVER_CLEAR_TIME && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2))) {
//dbg_printf("timeAfterCrashedMs = %d\n", runner.timeAfterCrashedMs);
// Enough time since the crash? runner.time froze there, updates stopped
int deltaTime = getTimeStamp() - runner.time;
if (key == RUNNER_KEYCODE_RESTART || (deltaTime >= RUNNER_GAMEOVER_CLEAR_TIME && isJumpKey(key))) {
runnerRestart();
}
}
else if (runner.paused && (key == RUNNER_KEYCODE_JUMP_1 || key == RUNNER_KEYCODE_JUMP_2)) {
trexReset();
runnerPlay();
}
}
void runnerClearCanvas() {
graphicsFillBackground(0xF7, 0xF7, 0xF7);
//graphicsRender();
graphicsFillBackground();
}
void runnerUpdate() {
//dbg_printf("runnerUpdate() runner.playing = %d\n", runner.playing);
//runner.updatePending = false;
int now = getTimeStamp();
//printf("now = %d\n", now);
int deltaTime = now - (runner.time ? runner.time : 0);
int deltaTime = now - runner.time;
if (deltaTime < 0) {
deltaTime = DELTA_MS_DEFAULT;
}
// dbg_printf("runnerUpdate() deltaTime = %d\n", deltaTime);
runner.time = now;
if (runner.playing) {
//printf("runnerUpdate() %d\n", getTimeStamp());
runnerClearCanvas();
if (trex.jumping) {
@@ -133,24 +82,23 @@ void runnerUpdate() {
// First jump triggers the intro.
if (trex.jumpCount == 1 && !runner.playingIntro) {
//printf("trex.jumpCount = %d\n", trex.jumpCount);
runnerPlayIntro();
}
// The horizon doesn't move until the intro is over.
if (runner.playingIntro) {
horizonUpdate(0, runner.currentSpeed, hasObstacles, false);
horizonUpdate(0, runner.currentSpeed, hasObstacles);
}
else {
deltaTime = !runner.activated ? 0 : deltaTime;
horizonUpdate(deltaTime, runner.currentSpeed, hasObstacles, runner.inverted);
horizonUpdate(deltaTime, runner.currentSpeed, hasObstacles);
}
// Check for collisions.
bool collision = hasObstacles && runnerCheckForCollision(horizon.obstacles->head->data);
bool collision = hasObstacles && horizon.obstacleCount > 0 && runnerCheckForCollision(&horizon.obstacles[0]);
if (!collision) {
runner.distanceRan += runner.currentSpeed * deltaTime / runner.msPerFrame;
runner.distanceRan += runner.currentSpeed * deltaTime / RUNNER_MS_PER_FRAME;
if (runner.currentSpeed < RUNNER_MAX_SPEED) {
runner.currentSpeed += RUNNER_ACCELERATION;
@@ -160,49 +108,21 @@ void runnerUpdate() {
runnerGameOver();
}
bool playAchievementSound = distanceMeterUpdate(deltaTime, (int)ceil(runner.distanceRan));
if (playAchievementSound) {
//this.playSound(this.soundFx.SCORE); // TODO
}
/*// Night mode.
if (this.invertTimer > this.config.INVERT_FADE_DURATION) {
this.invertTimer = 0;
this.invertTrigger = false;
this.invert();
}
else if (this.invertTimer) {
this.invertTimer += deltaTime;
}
else {
var actualDistance =
this.distanceMeter.getActualDistance(Math.ceil(this.distanceRan));
if (actualDistance > 0) {
this.invertTrigger = !(actualDistance %
this.config.INVERT_DISTANCE);
if (this.invertTrigger&& this.invertTimer == = 0) {
this.invertTimer += deltaTime;
this.invert();
}
}
}*/
// TODO sound: returns true when the achievement sound should play
distanceMeterUpdate(deltaTime, (int)ceil(runner.distanceRan));
}
runner.nextUpdateScheduled = false;//
runner.nextUpdateScheduled = false;
if (runner.playing || (!runner.activated && trex.blinkCount < RUNNER_MAX_BLINK_COUNT)) {
trexUpdate(deltaTime, -1);
runner.nextUpdateScheduled = true;
}
graphicsRender(); // blit all drawn to the screen
//printf("runner update end\n\n");
}
void runnerGameOver() {
// this.playSound(this.soundFx.HIT); // TODO
// TODO sound
runnerStop();
runner.crashed = true;
distanceMeter.achievement = false;
@@ -221,43 +141,23 @@ void runnerGameOver() {
void runnerStop() {
runner.playing = false;
runner.paused = true;
runner.isRunning = false;
}
void runnerPlay() {
if (!runner.crashed) {
runner.playing = true;
runner.paused = false;
trexUpdate(0, TREX_STATUS_RUNNING);
runner.time = getTimeStamp();
runnerUpdate();
}
}
void runnerRestart() {
if (!runner.isRunning) {
runner.playCount++;
runner.runningTime = 0;
runner.playing = true;
runner.crashed = false;
runner.timeAfterCrashedMs = 0;
runner.distanceRan = 0;
runner.currentSpeed = RUNNER_SPEED;
runner.time = getTimeStamp();
runnerClearCanvas();
distanceMeterReset(runner.highestScore);
horizonReset();
trexReset();
//this.playSound(this.soundFx.BUTTON_PRESS);
//this.invert(true);
runner.isRunning = true;
runnerUpdate();
}
runner.runningTime = 0;
runner.playing = true;
runner.crashed = false;
runner.distanceRan = 0;
runner.currentSpeed = RUNNER_SPEED;
runner.time = getTimeStamp();
runnerClearCanvas();
distanceMeterReset();
horizonReset();
trexReset();
runnerUpdate();
}
void runnerPlayIntro() {
//printf("runnerPlayIntro()\n");
if (!runner.activated && !runner.crashed) {
runner.playingIntro = true;
trex.playingIntro = true;
@@ -273,61 +173,43 @@ void runnerStartGame() {
runner.runningTime = 0;
runner.playingIntro = false;
trex.playingIntro = false;
runner.playCount++;
runner.isRunning = true;
}
CollisionBox createAdjustedCollisionBox(CollisionBox box, CollisionBox adjustment) {
return (CollisionBox){ .x = box.x + adjustment.x, .y = box.y + adjustment.y, .width = box.width, .height = box.height };
}
// Returns whether boxes intersected
bool boxCompare(CollisionBox tRexBox, CollisionBox obstacleBox) {
// Axis-Aligned Bounding Box method.
return (tRexBox.x < obstacleBox.x + obstacleBox.width &&
tRexBox.x + tRexBox.width > obstacleBox.x &&
tRexBox.y < obstacleBox.y + obstacleBox.height &&
tRexBox.height + tRexBox.y > obstacleBox.y);
// Axis-Aligned Bounding Box method.
static bool boxesIntersect(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh) {
return ax < bx + bw && ax + aw > bx && ay < by + bh && ay + ah > by;
}
bool runnerCheckForCollision(const Obstacle* obstacle) {
// Adjustments are made to the bounding box as there is a 1 pixel white
// border around the t-rex and obstacles.
CollisionBox tRexBox = {
.x = trex.xPos + 1,
.y = trex.yPos + 1,
.width = TREX_WIDTH - 2,
.height = TREX_HEIGHT - 2 };
CollisionBox obstacleBox = {
.x = obstacle->xPos + 1,
.y = obstacle->yPos + 1,
.width = obstacle->typeConfig.width * obstacle->size - 2,
.height = obstacle->typeConfig.height - 2 };
// border around the t-rex and obstacles.
int tx = trex.xPos + 1;
int ty = trex.yPos + 1;
int ox = obstacle->xPos + 1;
int oy = obstacle->yPos + 1;
int ow = obstacle->typeConfig.width * obstacle->size - 2;
int oh = obstacle->typeConfig.height - 2;
// Simple outer bounds check.
if (boxCompare(tRexBox, obstacleBox)) {
CollisionBox* tRexCollisionBoxes = &trexDuckingCollisionBox;
if (boxesIntersect(tx, ty, TREX_WIDTH - 2, TREX_HEIGHT - 2, ox, oy, ow, oh)) {
const CollisionBox* tRexCollisionBoxes = &trexDuckingCollisionBox;
int tRexCollisionBoxesCount = 1;
if (!trex.ducking) {
tRexCollisionBoxes = trexRunningCollisionBox;
tRexCollisionBoxesCount = 6;
}
// Detailed axis aligned box check.
// Detailed axis aligned box check with boxes adjusted to actual positions.
for (int t = 0; t < tRexCollisionBoxesCount; t++) {
const CollisionBox* tb = &tRexCollisionBoxes[t];
for (int i = 0; i < obstacle->typeConfig.collisionBoxesCount; i++) {
// Adjust the box to actual positions.
CollisionBox adjTrexBox = createAdjustedCollisionBox(tRexCollisionBoxes[t], tRexBox);
CollisionBox adjObstacleBox = createAdjustedCollisionBox(obstacle->typeConfig.collisionBoxes[i], obstacleBox);
if (boxCompare(adjTrexBox, adjObstacleBox)) {
return true;// [adjTrexBox, adjObstacleBox] ;
const CollisionBox* cb = &obstacle->typeConfig.collisionBoxes[i];
if (boxesIntersect(tb->x + tx, tb->y + ty, tb->width, tb->height,
cb->x + ox, cb->y + oy, cb->width, cb->height)) {
return true;
}
}
}
}
return false;
}
+7 -41
View File
@@ -2,77 +2,44 @@
#define RUNNER_H
#include <stdbool.h>
#include <math.h>
#include "config.h"
#include "ulist.h"
#include "graphics.h"
#include "horizon.h"
#include "distance_meter.h"
#include "game_over_panel.h"
#include "trex.h"
#define RUNNER_DEFAULT_HEIGHT 150
#define RUNNER_ACCELERATION 0.001
#define RUNNER_BG_CLOUD_SPEED 0.2
#define RUNNER_BOTTOM_PAD 10
#define RUNNER_CLEAR_TIME 3000
#define RUNNER_CLOUD_FREQUENCY 0.5
#define RUNNER_GAMEOVER_CLEAR_TIME 750
#define RUNNER_GAP_COEFFICIENT 0.6
#define RUNNER_GRAVITY 0.6
#define RUNNER_INITIAL_JUMP_VELOCITY 12
#define RUNNER_INVERT_FADE_DURATION 12000
#define RUNNER_INVERT_DISTANCE 700
#define RUNNER_MAX_BLINK_COUNT 3
#define RUNNER_MAX_CLOUDS 6
#define RUNNER_MAX_OBSTACLE_LENGTH 3
#define RUNNER_MAX_OBSTACLE_DUPLICATION 2
#define RUNNER_MS_PER_FRAME (1000.0 / FPS)
#define RUNNER_MAX_SPEED 13.0
#define RUNNER_MIN_JUMP_HEIGHT 35
#define RUNNER_MOBILE_SPEED_COEFFICIENT 1.2
#define RUNNER_SPEED 6.0
#define RUNNER_SPEED_DROP_COEFFICIENT 3
#define RUNNER_KEYCODE_JUMP_1 82
#define RUNNER_KEYCODE_JUMP_2 32
#define RUNNER_KEYCODE_DUCK 81
#define RUNNER_KEYCODE_RESTART 13
// Scancodes; 0x100 marks the E0 extended prefix
#define RUNNER_KEYCODE_JUMP_1 0x148 // up arrow
#define RUNNER_KEYCODE_JUMP_2 0x39 // space
#define RUNNER_KEYCODE_DUCK 0x150 // down arrow
#define RUNNER_KEYCODE_RESTART 0x1C // enter
typedef struct {
int width;
int height;
double distanceRan;
int highestScore;
int time;
int runningTime;
double msPerFrame;
double azazzaza; //
double currentSpeed;
// Ulist* obstacles;
bool activated;
bool playing;
bool crashed;
int timeAfterCrashedMs;
bool paused;
bool inverted;
bool invertTimer;
bool playingIntro;
bool isRunning;
// resizeTimerId_
int playCount;
// soundFx
// audioContext
// images
// imagesLoaded
bool nextUpdateScheduled;
bool skipUpdateNow;
} Runner;
extern Runner runner;
void runnerInit();
void runnerAdjustDimensions();
//void runnerLoadImages();
void runnerClearCanvas();
@@ -83,7 +50,6 @@ void runnerOnKeyDown(int key);
void runnerOnKeyUp(int key);
void runnerGameOver();
void runnerStop();
void runnerPlay();
void runnerRestart();
bool runnerCheckForCollision(const Obstacle *obstacle);
+81 -169
View File
@@ -1,169 +1,81 @@
// Original chrome dino sprite pack
static const char sprites100[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x04, 0xd1, 0x00, 0x00, 0x00, 0x44, 0x08, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x23, 0xfc,
0x41, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x76, 0x93, 0xcd, 0x38, 0x00,
0x00, 0x0a, 0x0e, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0xec, 0x9d, 0x5b, 0x76, 0xa4, 0xb8, 0x16,
0x44, 0x83, 0xbb, 0xb8, 0x0f, 0x4d, 0x84, 0xa1, 0xd8, 0x03, 0x80, 0x4f, 0x0d, 0x4f, 0x9f, 0xa9,
0x01, 0x54, 0x0d, 0x85, 0x89, 0xe8, 0x93, 0xae, 0x57, 0xac, 0xab, 0xaa, 0x68, 0xf2, 0x58, 0x2d,
0xd2, 0x98, 0xf4, 0xd9, 0xbd, 0x3a, 0x13, 0x9f, 0x07, 0x95, 0x18, 0x57, 0x38, 0x24, 0x01, 0x05,
0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xe7, 0xc3, 0x31, 0xe0, 0x3b, 0x05, 0xf7, 0x08, 0x38, 0x8e,
0x15, 0xc0, 0x84, 0x83, 0x29, 0x08, 0x6f, 0x2b, 0x43, 0xb8, 0x1f, 0xd8, 0x80, 0xa1, 0xb7, 0x85,
0x65, 0x2c, 0x7c, 0x58, 0x82, 0xb4, 0x76, 0xac, 0xf8, 0xce, 0xd4, 0x11, 0x83, 0x55, 0xdd, 0x10,
0x23, 0x5f, 0x5f, 0xf0, 0x93, 0x19, 0x40, 0xe6, 0x36, 0x32, 0x43, 0x3f, 0xa3, 0x33, 0xb8, 0xc9,
0xca, 0x2a, 0xc4, 0x34, 0x63, 0xe0, 0x26, 0xcb, 0x19, 0xe2, 0xae, 0xea, 0xe6, 0xc7, 0x52, 0xa0,
0x84, 0x0b, 0xd6, 0x5e, 0x80, 0x11, 0x00, 0x4a, 0xc4, 0x3d, 0x4a, 0x40, 0x07, 0xf2, 0xb3, 0xbc,
0xae, 0x98, 0x70, 0x02, 0x25, 0xf2, 0x50, 0xf6, 0x02, 0xdb, 0x02, 0x6c, 0x43, 0x4f, 0x4b, 0x55,
0xc6, 0xc2, 0xa3, 0x13, 0x4a, 0x7b, 0xc7, 0x84, 0xd3, 0x98, 0x80, 0x15, 0x77, 0x98, 0xa9, 0x64,
0x94, 0xa0, 0xea, 0x3d, 0x4b, 0x21, 0x31, 0x42, 0x33, 0xb2, 0xec, 0xe5, 0x39, 0x71, 0x46, 0x5b,
0xd0, 0x10, 0x4b, 0x40, 0xbf, 0x96, 0xff, 0xd0, 0x31, 0x6a, 0xda, 0x84, 0xe3, 0x28, 0x88, 0xa6,
0x4b, 0xe3, 0x51, 0xf2, 0x50, 0x24, 0x40, 0x75, 0xc2, 0xb2, 0x0d, 0x1d, 0x2d, 0x55, 0x19, 0x0b,
0x0f, 0x4f, 0xa8, 0x57, 0xb4, 0x3b, 0xc8, 0xba, 0x1f, 0x9b, 0xac, 0x3a, 0xac, 0xa6, 0xdd, 0xae,
0x63, 0x54, 0x2f, 0xa3, 0x4e, 0xc9, 0xaa, 0x4c, 0xb4, 0x67, 0x14, 0xba, 0x2c, 0x59, 0xd9, 0x64,
0x87, 0x6e, 0xc9, 0x7e, 0x33, 0xde, 0xc1, 0xa1, 0x45, 0xfc, 0x4e, 0xba, 0x72, 0xad, 0xf1, 0x9b,
0x24, 0x9f, 0xac, 0x68, 0x14, 0x34, 0x5b, 0xd2, 0x3a, 0x8e, 0x7c, 0x45, 0xfd, 0x93, 0xbe, 0xe2,
0x7a, 0xa8, 0xeb, 0xa1, 0x90, 0x9d, 0xea, 0x37, 0xdb, 0x99, 0x1e, 0x52, 0x3b, 0x61, 0xed, 0xb1,
0x69, 0x5f, 0x7f, 0x0c, 0x3b, 0xa9, 0x5b, 0x33, 0xe6, 0x4c, 0x69, 0xe3, 0x98, 0x11, 0x32, 0x12,
0xcd, 0x8c, 0xcd, 0xf5, 0x68, 0xb2, 0xee, 0xc8, 0x6e, 0xca, 0x3e, 0x1d, 0x23, 0xde, 0x89, 0x49,
0x05, 0xee, 0x38, 0xc4, 0xa5, 0x59, 0xca, 0xa4, 0x81, 0x0d, 0x83, 0x4a, 0x55, 0x5d, 0x51, 0x22,
0x1b, 0x59, 0xb5, 0x6c, 0xda, 0xf2, 0x78, 0xd4, 0x2b, 0xda, 0x74, 0x3b, 0x34, 0x8d, 0x31, 0x3a,
0xdd, 0x8f, 0x4d, 0x58, 0xed, 0xba, 0xaf, 0x7c, 0x7d, 0x31, 0x4d, 0xc0, 0xcc, 0x31, 0xa4, 0xd6,
0x64, 0x16, 0x66, 0xed, 0x81, 0x86, 0xde, 0x95, 0x68, 0xfc, 0xc4, 0x5e, 0xb9, 0x76, 0xd6, 0x08,
0xf2, 0x65, 0x15, 0xcd, 0x3e, 0x72, 0x85, 0x23, 0xcf, 0x93, 0x26, 0x74, 0x4a, 0x2c, 0x41, 0x03,
0xdb, 0x82, 0x4d, 0xa5, 0xaa, 0xaa, 0x28, 0x11, 0xb1, 0xfc, 0x2e, 0x68, 0x58, 0xb4, 0xa5, 0x05,
0x1d, 0x3e, 0x3e, 0x9e, 0x09, 0xe7, 0x23, 0x36, 0xed, 0x85, 0x72, 0x76, 0x9f, 0x2c, 0x5f, 0x8a,
0x7e, 0x49, 0x41, 0x9e, 0xeb, 0xad, 0x53, 0xb9, 0x61, 0x39, 0x63, 0xbf, 0x1d, 0xb5, 0xc0, 0xd2,
0x5f, 0x7b, 0xbe, 0xa2, 0xa5, 0x88, 0x36, 0x32, 0xe6, 0x46, 0x6f, 0xb0, 0x4e, 0xc0, 0x54, 0x25,
0x6a, 0x4a, 0xd3, 0xaa, 0x4a, 0x69, 0x76, 0x69, 0x25, 0xd6, 0xe6, 0x86, 0x81, 0xff, 0x2d, 0xc0,
0x72, 0xab, 0xa4, 0x6a, 0xf8, 0xb3, 0x02, 0xfb, 0xb0, 0xe5, 0xf8, 0xe1, 0x63, 0xbf, 0x38, 0xf6,
0x39, 0xb4, 0x49, 0x63, 0xfb, 0x4e, 0x6b, 0x5a, 0xff, 0xb9, 0x4b, 0xc3, 0xcb, 0xd7, 0x7d, 0x41,
0xa3, 0xf3, 0xe2, 0xeb, 0x4c, 0x3f, 0xa6, 0x43, 0xca, 0xcc, 0x6c, 0x3d, 0xe4, 0x9c, 0x7f, 0x7c,
0xa5, 0xcb, 0xa6, 0xce, 0x7d, 0x16, 0xdc, 0x7a, 0x6b, 0x4f, 0x60, 0x44, 0xaf, 0xa4, 0x09, 0xf6,
0xd0, 0x64, 0x92, 0xd1, 0xe7, 0xd5, 0x28, 0xe1, 0x9c, 0xe1, 0xa3, 0x50, 0x82, 0x88, 0xe3, 0xd5,
0x99, 0xf3, 0xbd, 0x31, 0x27, 0x93, 0x1a, 0xb3, 0x39, 0x57, 0xc6, 0x96, 0x53, 0xf7, 0xcb, 0xda,
0xa7, 0x67, 0x44, 0xb7, 0xa4, 0xcd, 0xa6, 0x2b, 0x98, 0xcc, 0xc1, 0x07, 0x29, 0x88, 0xc6, 0xf5,
0x65, 0x5a, 0x9d, 0x90, 0x10, 0x0d, 0x97, 0x56, 0x82, 0x15, 0xb0, 0x5b, 0x74, 0xe4, 0x7a, 0x3e,
0xfc, 0x20, 0xb6, 0x38, 0xae, 0xf6, 0xf9, 0x31, 0xeb, 0x48, 0xeb, 0x5c, 0xda, 0x6a, 0xd7, 0x91,
0x3c, 0xcb, 0x08, 0x73, 0xff, 0x6b, 0x5b, 0xcc, 0x64, 0x10, 0xc1, 0x0e, 0x1b, 0xe7, 0xd6, 0x5f,
0x7b, 0xb6, 0xa2, 0xa5, 0x5a, 0xd2, 0x12, 0x10, 0x8f, 0xf2, 0x66, 0x46, 0xd5, 0x49, 0x73, 0x67,
0x6d, 0x2d, 0x3a, 0x0c, 0x3d, 0x1f, 0x0e, 0xa1, 0xaf, 0x30, 0x8b, 0x66, 0x2c, 0x8e, 0x6e, 0xa0,
0xa4, 0x55, 0xab, 0x99, 0x14, 0x2d, 0x0e, 0x3c, 0xbf, 0x27, 0xa9, 0x4a, 0xe4, 0xff, 0x31, 0xcd,
0xd6, 0x0a, 0x29, 0x39, 0xf9, 0x33, 0x9e, 0x01, 0xf7, 0x7e, 0xff, 0x12, 0x41, 0xab, 0xb6, 0xd2,
0x3b, 0x4c, 0x43, 0x4f, 0x55, 0x51, 0x29, 0xb1, 0x41, 0x44, 0xb5, 0x3a, 0xc6, 0x52, 0x0c, 0x05,
0x92, 0xc0, 0xa3, 0x45, 0xab, 0x94, 0xb2, 0x97, 0x30, 0x3a, 0x3e, 0x11, 0x5f, 0xf8, 0xea, 0x38,
0xc7, 0x79, 0xb4, 0xa4, 0x4b, 0x98, 0x29, 0x76, 0xf8, 0xb3, 0x95, 0x8b, 0x00, 0x06, 0x93, 0xd6,
0x5c, 0x1f, 0x73, 0x72, 0xab, 0xe8, 0x20, 0xd9, 0xe8, 0x90, 0xfa, 0x86, 0xb5, 0x02, 0x59, 0x58,
0x66, 0x8c, 0x71, 0x6b, 0xcc, 0xd9, 0x35, 0xee, 0x9c, 0x56, 0x8d, 0xd1, 0xa5, 0xfd, 0x88, 0xbd,
0x02, 0xe0, 0x6b, 0x06, 0xa0, 0x1b, 0xba, 0xc9, 0xaf, 0x18, 0xd3, 0x42, 0xc9, 0x6a, 0x5b, 0x86,
0xf3, 0xd4, 0xf3, 0x68, 0xf5, 0x68, 0x33, 0x22, 0xf5, 0x0d, 0x38, 0xa7, 0xc6, 0x8b, 0x69, 0x0b,
0x62, 0xc3, 0xba, 0x65, 0x5d, 0x9d, 0x00, 0xed, 0x3c, 0x03, 0x4a, 0x88, 0xce, 0xfc, 0x6b, 0x02,
0x88, 0x09, 0xc4, 0xea, 0xa0, 0x06, 0x86, 0x0e, 0x39, 0xfd, 0xe0, 0x2e, 0xed, 0xcb, 0x2b, 0xba,
0x71, 0x9c, 0x11, 0x4a, 0x44, 0x37, 0x93, 0x6c, 0x5d, 0x80, 0xe5, 0x51, 0x8e, 0x8c, 0x89, 0xee,
0xbb, 0x50, 0x63, 0xd3, 0x3e, 0x28, 0x8e, 0xd7, 0x19, 0x74, 0xbe, 0x02, 0xd8, 0xbd, 0x7b, 0x7c,
0xde, 0x09, 0x66, 0xbe, 0x4b, 0xb1, 0xee, 0x47, 0xba, 0x59, 0xd1, 0xb3, 0xcf, 0xb9, 0x8a, 0x9a,
0x24, 0x90, 0x33, 0x6b, 0x9f, 0x98, 0xf1, 0x28, 0x41, 0x4b, 0xfd, 0x77, 0x67, 0xee, 0xde, 0x31,
0x1a, 0xcc, 0x6a, 0x9c, 0xef, 0xd2, 0x54, 0x42, 0x34, 0x71, 0x82, 0x1a, 0x19, 0x4f, 0xd1, 0x68,
0x88, 0x99, 0xe3, 0xce, 0xf6, 0xd8, 0xb4, 0x32, 0x46, 0x39, 0x73, 0x9c, 0xa3, 0x15, 0x2d, 0xe2,
0x13, 0x32, 0x6c, 0x0b, 0x9c, 0x13, 0x79, 0xe5, 0xa0, 0x93, 0xce, 0x48, 0x98, 0x79, 0xbf, 0xa7,
0x26, 0xf2, 0x0c, 0x05, 0x5a, 0xb9, 0xe7, 0xef, 0x66, 0xa3, 0xd6, 0xdc, 0x67, 0xbd, 0x1f, 0xb9,
0x46, 0xbc, 0xe8, 0x5f, 0x2f, 0x24, 0x04, 0xe0, 0x12, 0xb5, 0x60, 0x6d, 0xc3, 0xf7, 0xe8, 0x1a,
0xf7, 0x75, 0x36, 0x7c, 0x97, 0xfa, 0x1d, 0x9a, 0xf8, 0xb5, 0xd0, 0x50, 0x7d, 0x97, 0x28, 0x01,
0x53, 0xd2, 0xe2, 0xe9, 0x8b, 0xd6, 0xf2, 0xcd, 0x78, 0x36, 0xbe, 0xbc, 0xf2, 0xf5, 0x9e, 0x9e,
0x01, 0x99, 0xaa, 0x21, 0x49, 0xc7, 0xa1, 0xa2, 0x7d, 0x3e, 0x52, 0x28, 0x7f, 0x06, 0x80, 0x61,
0x03, 0x16, 0xbb, 0xa5, 0xe2, 0xb6, 0xe0, 0x04, 0xea, 0xf5, 0x81, 0x82, 0x27, 0xe1, 0x95, 0xaf,
0xd7, 0xa7, 0x70, 0xa5, 0xaa, 0x3a, 0x45, 0x11, 0x24, 0x5d, 0xb7, 0x96, 0x7e, 0x58, 0x22, 0x24,
0x43, 0xaf, 0x2f, 0x1c, 0xd0, 0x40, 0x5f, 0x2b, 0x19, 0x1f, 0x70, 0xa6, 0xba, 0xe7, 0xe1, 0x22,
0x74, 0x6e, 0xac, 0x26, 0xa0, 0xbc, 0xb9, 0x3a, 0x40, 0xd5, 0xe9, 0x6f, 0x03, 0x03, 0x36, 0xfa,
0x2e, 0xbb, 0xe5, 0x67, 0xfd, 0xf2, 0xde, 0x56, 0x8d, 0xeb, 0x03, 0x4f, 0x38, 0x3f, 0x30, 0x18,
0x8b, 0x00, 0xed, 0xcc, 0x1d, 0x63, 0x20, 0x1d, 0xc9, 0x9a, 0xfb, 0x9c, 0xd1, 0x8a, 0xb3, 0x41,
0x19, 0x3a, 0x5b, 0x47, 0x7c, 0x2e, 0x12, 0x10, 0xf6, 0x03, 0xe4, 0x36, 0x14, 0xa9, 0x10, 0x68,
0xeb, 0xd8, 0x72, 0x96, 0xe1, 0x7c, 0x8e, 0xbb, 0x39, 0xed, 0x87, 0x1f, 0xcc, 0xfb, 0xc5, 0x7f,
0x5b, 0x9f, 0xbb, 0xfe, 0xf4, 0x59, 0xf7, 0x20, 0x11, 0x43, 0x82, 0xf9, 0x6b, 0x5f, 0x08, 0x20,
0x17, 0xad, 0x25, 0xb3, 0x75, 0xf3, 0xfa, 0x06, 0x60, 0xd8, 0xd1, 0x1f, 0x0c, 0x87, 0xb7, 0xaa,
0xa2, 0x25, 0x28, 0xfd, 0x47, 0x6e, 0x73, 0x67, 0x9e, 0x4c, 0xed, 0x48, 0xaa, 0xea, 0xed, 0xea,
0x82, 0x50, 0xc5, 0xd8, 0xa9, 0x81, 0x0a, 0xaa, 0x93, 0x56, 0xa8, 0x4d, 0x3b, 0x46, 0xd0, 0x4a,
0x9f, 0xa0, 0xc5, 0x12, 0x64, 0x57, 0xd7, 0xe2, 0xeb, 0xcb, 0x8f, 0xff, 0x3f, 0x13, 0xce, 0x06,
0x1d, 0xde, 0xdc, 0xb0, 0xf5, 0xb4, 0x0e, 0xa8, 0x15, 0x2d, 0xa6, 0x67, 0x5d, 0xf7, 0x0c, 0x25,
0x1a, 0x81, 0x8a, 0x1b, 0x30, 0xec, 0xb4, 0xc4, 0x7b, 0x2d, 0x1d, 0x44, 0xb4, 0x43, 0x69, 0xe7,
0xcd, 0x9d, 0xd7, 0x3e, 0x63, 0x2f, 0x7c, 0x86, 0xad, 0xce, 0xfd, 0xcb, 0xcd, 0xe9, 0x4a, 0xc6,
0xc1, 0x64, 0x7a, 0xae, 0x36, 0x5b, 0x97, 0x65, 0xde, 0x43, 0x7e, 0xd7, 0x8a, 0x6d, 0xb8, 0x5a,
0x2d, 0xcf, 0x8e, 0x9e, 0x0a, 0x75, 0xb5, 0x4b, 0x25, 0x51, 0x4b, 0xc3, 0xbd, 0xed, 0x5d, 0xad,
0x23, 0xee, 0x48, 0x5a, 0x04, 0xda, 0x8f, 0xfc, 0x00, 0x82, 0xfa, 0xae, 0xca, 0x42, 0x86, 0xb6,
0xea, 0x66, 0x49, 0x1b, 0xd0, 0xde, 0x72, 0x84, 0xd6, 0xb6, 0x13, 0x70, 0x7d, 0xe4, 0x19, 0xb6,
0xbc, 0xdf, 0xbc, 0x9b, 0xf9, 0x9e, 0xde, 0x51, 0x3d, 0x59, 0xa1, 0xa9, 0xdc, 0xb6, 0xcf, 0x3c,
0x37, 0x3f, 0xbb, 0xd5, 0x59, 0xa0, 0x91, 0x5b, 0x67, 0xeb, 0xa8, 0x0a, 0xf6, 0x8c, 0x84, 0x02,
0x44, 0x0d, 0x34, 0xb6, 0xc4, 0xe3, 0xbf, 0x4d, 0xdc, 0xe9, 0xf9, 0x7b, 0x3a, 0x0b, 0x79, 0x86,
0xed, 0xf5, 0xe1, 0x9d, 0x79, 0x51, 0xe2, 0x09, 0xf1, 0xe2, 0xb5, 0xd4, 0xed, 0xd9, 0x9a, 0xfc,
0x54, 0xe5, 0xd1, 0x84, 0xb6, 0xf5, 0xb7, 0x8e, 0x8f, 0x3b, 0x53, 0xc7, 0xa3, 0x4e, 0x50, 0x5d,
0x9a, 0x56, 0xb3, 0x44, 0x7b, 0xf6, 0xd9, 0x6b, 0x89, 0xba, 0xfa, 0x79, 0xae, 0x10, 0x95, 0x00,
0x6e, 0x71, 0x4f, 0xd7, 0x9c, 0x47, 0xfb, 0xfe, 0xdf, 0x1d, 0x4f, 0xc5, 0x60, 0x6e, 0x8b, 0x1b,
0xe4, 0xa6, 0x54, 0xbe, 0x5b, 0x9a, 0x71, 0x59, 0xfc, 0x7a, 0x34, 0x27, 0x85, 0x8f, 0xe0, 0xd2,
0xb8, 0x28, 0xc0, 0xad, 0x4b, 0xbb, 0xb4, 0xa7, 0xf0, 0x68, 0xf6, 0x78, 0x27, 0x5d, 0xb7, 0xd6,
0x5e, 0x75, 0x6e, 0xfc, 0x37, 0x0d, 0x74, 0x67, 0xfd, 0xad, 0x18, 0x1f, 0x79, 0xa6, 0xfa, 0xb1,
0x67, 0xd1, 0xd4, 0xa5, 0xd9, 0xd5, 0x9d, 0x24, 0x63, 0xbf, 0xa5, 0xde, 0xb2, 0x13, 0xa1, 0x00,
0x88, 0x9a, 0x20, 0xf6, 0x53, 0xdc, 0xb8, 0x15, 0xea, 0x45, 0x68, 0x79, 0xb8, 0xe2, 0x3a, 0x49,
0x8c, 0x34, 0xc6, 0x94, 0xe9, 0x9f, 0xc5, 0x56, 0xc6, 0x1c, 0xc7, 0x3d, 0xda, 0x79, 0x04, 0x5b,
0xf3, 0xeb, 0xad, 0x14, 0x8a, 0x26, 0x2a, 0xa3, 0x17, 0x80, 0xa2, 0x1d, 0xaa, 0x81, 0x36, 0xa1,
0x2e, 0x2c, 0xfc, 0x43, 0x2e, 0xc1, 0x8b, 0xff, 0xec, 0x5c, 0xbc, 0x56, 0xaf, 0x6c, 0xba, 0x61,
0xe9, 0x6f, 0x3d, 0x4d, 0xd1, 0xc2, 0xc3, 0x9c, 0x19, 0x09, 0x6d, 0xb3, 0x5e, 0x08, 0x1f, 0x7b,
0x84, 0xaa, 0x71, 0xcd, 0xa8, 0x06, 0x16, 0x18, 0x48, 0x07, 0x3e, 0x11, 0x8e, 0x33, 0x1a, 0x13,
0x39, 0xfe, 0xd7, 0xa2, 0x77, 0x4a, 0x2c, 0x05, 0x26, 0x9a, 0x04, 0x2d, 0xc5, 0xfe, 0xf3, 0xc0,
0x8e, 0xfa, 0x71, 0xb1, 0xd0, 0xf1, 0xe4, 0x3a, 0x75, 0x8e, 0x3b, 0x27, 0x23, 0xb6, 0x3e, 0xf7,
0x98, 0x53, 0xe7, 0x3f, 0x9e, 0xae, 0x96, 0x64, 0xcc, 0x1f, 0xdd, 0xa5, 0x8d, 0xb0, 0x25, 0x2d,
0x05, 0x3d, 0xf2, 0xc7, 0xd3, 0xfc, 0x2c, 0x8f, 0xf0, 0x21, 0x25, 0x2d, 0x05, 0x26, 0xe4, 0xda,
0x58, 0xe3, 0xdb, 0x1d, 0x61, 0x5b, 0x37, 0xff, 0x55, 0x74, 0x25, 0x12, 0xc2, 0xd3, 0xd6, 0xe6,
0x0f, 0x35, 0x8f, 0x66, 0x8c, 0x65, 0x42, 0xc3, 0x91, 0xbb, 0x4b, 0x13, 0xe1, 0x92, 0x04, 0xa3,
0x82, 0x74, 0x68, 0x82, 0x51, 0x1b, 0x55, 0x4d, 0x71, 0x69, 0xa7, 0xb2, 0x82, 0xb8, 0x4b, 0x73,
0x97, 0x76, 0xeb, 0x69, 0x55, 0x45, 0x43, 0xe8, 0x3f, 0xf2, 0x7e, 0x9e, 0x42, 0x29, 0x7f, 0x5f,
0x6e, 0x0c, 0x9a, 0x30, 0x08, 0x7b, 0xea, 0x18, 0x24, 0xda, 0xb0, 0x2b, 0x63, 0x3c, 0xb9, 0x4e,
0x66, 0x5d, 0xcf, 0x3a, 0xe7, 0x6a, 0xd7, 0x39, 0x8e, 0xaf, 0x75, 0x9e, 0x8d, 0xbd, 0xdc, 0xa8,
0x89, 0x76, 0x75, 0x8c, 0x1a, 0x8d, 0x70, 0x2e, 0xe8, 0xd2, 0xd2, 0x95, 0x6b, 0x0d, 0x97, 0x96,
0x5b, 0x5d, 0x1a, 0xcd, 0x15, 0x53, 0x0b, 0x18, 0x19, 0x3a, 0x5b, 0xc7, 0x03, 0xce, 0xd4, 0x95,
0xdc, 0x53, 0xb8, 0x13, 0x18, 0xb6, 0x1f, 0xaf, 0x1d, 0x2d, 0xc7, 0xab, 0x63, 0xb1, 0x6f, 0xcf,
0xb2, 0x31, 0xdd, 0xd7, 0x8a, 0x76, 0x97, 0xe6, 0x0e, 0xcd, 0x71, 0x8f, 0x76, 0x2a, 0xc1, 0x0c,
0x0c, 0x1d, 0x2d, 0xef, 0x6c, 0x01, 0xfe, 0x78, 0x20, 0x48, 0x7c, 0xeb, 0x32, 0xc0, 0xda, 0xa4,
0x23, 0xeb, 0x84, 0x86, 0x62, 0x9f, 0x44, 0x33, 0xae, 0xf8, 0x0e, 0x4f, 0x51, 0xab, 0x2e, 0x2d,
0x63, 0x9f, 0x01, 0xd8, 0xc4, 0x6a, 0x55, 0x16, 0x4e, 0x22, 0xbd, 0xad, 0xe3, 0x81, 0x67, 0xca,
0x67, 0xd1, 0xce, 0x5c, 0x89, 0x48, 0xe1, 0xc1, 0x2e, 0x0d, 0xab, 0x3b, 0x34, 0xa7, 0x9f, 0x9b,
0xf1, 0x8c, 0x8d, 0xce, 0xd6, 0x11, 0xd7, 0xc7, 0x25, 0x4d, 0x6f, 0xcc, 0xea, 0xb7, 0x69, 0x8d,
0x8b, 0xa3, 0xab, 0x1b, 0x34, 0x7d, 0x7a, 0x03, 0xdf, 0x1f, 0x54, 0x0b, 0x44, 0x44, 0x20, 0x15,
0x20, 0xec, 0xd7, 0xb2, 0xb2, 0xff, 0x33, 0xa8, 0x4b, 0xe3, 0xbb, 0xc1, 0x52, 0x4d, 0x7c, 0xdd,
0x5a, 0xc6, 0x38, 0x75, 0xd3, 0xc2, 0xfd, 0xdc, 0x6f, 0x1d, 0x1f, 0x7b, 0xa6, 0x7a, 0x5c, 0x7b,
0x80, 0x63, 0x13, 0x0a, 0xe2, 0xdb, 0x6d, 0xf2, 0x44, 0x41, 0x91, 0x18, 0x85, 0xae, 0x8a, 0x19,
0x36, 0xcd, 0xf6, 0x5d, 0xab, 0xfb, 0x33, 0x67, 0xdb, 0x19, 0x30, 0x2e, 0x7c, 0xe8, 0xac, 0xd5,
0xaa, 0xb0, 0xb5, 0x4f, 0xd1, 0xe6, 0x86, 0x5c, 0xc6, 0x7b, 0xe2, 0x92, 0xd6, 0x0c, 0xd5, 0xcb,
0x2f, 0x43, 0x7b, 0xf8, 0x64, 0x67, 0x02, 0x67, 0x6a, 0xc2, 0x03, 0x6a, 0x13, 0x83, 0xbb, 0xb5,
0x09, 0x11, 0x11, 0x09, 0xa9, 0xfb, 0x33, 0x28, 0xb9, 0xd5, 0xa5, 0x01, 0x37, 0x0c, 0x68, 0x84,
0x4d, 0xdb, 0xc1, 0x2b, 0x03, 0x99, 0xef, 0xf6, 0x91, 0x7f, 0xe8, 0xfb, 0x44, 0x9d, 0xa9, 0x3f,
0xd6, 0xbf, 0x07, 0xe7, 0x79, 0x51, 0x47, 0xa6, 0xdc, 0x7e, 0xe6, 0x1e, 0xd0, 0x3a, 0xc2, 0x71,
0x9c, 0x4b, 0xde, 0xf7, 0x64, 0xd7, 0xd3, 0xc7, 0x05, 0x94, 0x33, 0xef, 0x7b, 0xba, 0x01, 0x3d,
0x0e, 0x0d, 0x95, 0x86, 0x6d, 0x30, 0x18, 0xdf, 0x75, 0x1d, 0xd2, 0x71, 0x1c, 0x67, 0x78, 0x60,
0xeb, 0x88, 0x26, 0x66, 0x38, 0x8e, 0xf3, 0x56, 0x22, 0x0a, 0x42, 0xb5, 0x75, 0x7c, 0xad, 0x05,
0xab, 0x8e, 0xff, 0x0c, 0x33, 0xb2, 0x6c, 0x41, 0xa9, 0xcd, 0xd5, 0x22, 0x13, 0xfa, 0x0d, 0x53,
0x70, 0xe4, 0x58, 0x45, 0xcb, 0x00, 0xd2, 0xdb, 0x8f, 0xdc, 0x29, 0xe1, 0xd1, 0x09, 0xd2, 0xdf,
0xa1, 0x38, 0x8e, 0xdf, 0x33, 0x30, 0xe7, 0xcf, 0xae, 0x61, 0x45, 0xff, 0x1d, 0x80, 0xf6, 0x04,
0xb1, 0x13, 0x8a, 0x76, 0x38, 0x67, 0x90, 0x64, 0xeb, 0xe8, 0xda, 0x16, 0x8e, 0xfd, 0x0c, 0x59,
0xb7, 0x2c, 0x6e, 0x10, 0xfa, 0x9a, 0xfa, 0xaf, 0xde, 0xc8, 0xe6, 0x91, 0xfb, 0xa5, 0x1b, 0x25,
0x96, 0x08, 0x90, 0x50, 0x42, 0x7b, 0x42, 0xc4, 0x91, 0x09, 0xd3, 0x76, 0x69, 0x87, 0xe3, 0xb8,
0x47, 0x33, 0x34, 0x39, 0xe8, 0x96, 0x53, 0xcb, 0x48, 0xa9, 0xbf, 0xec, 0x48, 0x50, 0xea, 0x98,
0x10, 0xdb, 0x25, 0x0a, 0xa7, 0x1d, 0xce, 0x69, 0x04, 0xd9, 0x3a, 0xb6, 0xb6, 0x81, 0xfe, 0xcf,
0xd0, 0xcf, 0xd0, 0xdf, 0xe4, 0x9c, 0x4c, 0x99, 0x4b, 0x5f, 0xa2, 0xa0, 0x10, 0x26, 0xf8, 0xf6,
0x1d, 0x36, 0x94, 0x52, 0xee, 0x74, 0xfc, 0xd5, 0xce, 0x7d, 0x25, 0x35, 0x0c, 0x04, 0x51, 0x14,
0x1d, 0xad, 0xf1, 0xae, 0x73, 0xd6, 0xa7, 0x5f, 0x7e, 0x00, 0x23, 0x39, 0x36, 0xd5, 0xcf, 0xf1,
0x1e, 0x32, 0xd8, 0x0a, 0x8f, 0xc9, 0x53, 0x65, 0xb5, 0x90, 0xb4, 0xe6, 0xff, 0xb0, 0x5e, 0x3f,
0xb9, 0x24, 0x49, 0x92, 0x24, 0x65, 0xb8, 0xf4, 0x26, 0x11, 0xd9, 0x80, 0x37, 0x40, 0x83, 0x95,
0x1e, 0x00, 0x0e, 0x9f, 0xf5, 0xff, 0x00, 0xaf, 0xff, 0xde, 0x31, 0x9a, 0x94, 0xc6, 0xcf, 0x20,
0x82, 0xce, 0xc1, 0x84, 0x01, 0x1a, 0xac, 0xf4, 0x00, 0xb0, 0xf9, 0xbe, 0x87, 0x01, 0x6e, 0xb3,
0x84, 0xa7, 0x1b, 0xa3, 0x31, 0xde, 0x92, 0x34, 0xc7, 0x01, 0x17, 0xfe, 0xcc, 0xa8, 0x30, 0xc0,
0xed, 0x78, 0xed, 0x31, 0xd7, 0xb4, 0x25, 0x09, 0xde, 0x66, 0xfc, 0x26, 0xd7, 0xd1, 0x24, 0xec,
0xf6, 0x6d, 0xd1, 0x0e, 0x08, 0x17, 0x04, 0xba, 0x4a, 0x5a, 0xfe, 0x52, 0xf3, 0x77, 0x92, 0x17,
0xbf, 0x3b, 0xcb, 0x55, 0x9d, 0xe5, 0xaa, 0x6e, 0x09, 0xc5, 0xc3, 0x1c, 0x5b, 0xb4, 0x1c, 0xbd,
0x70, 0x3c, 0x66, 0xe1, 0xcf, 0xa9, 0x4b, 0xd9, 0x62, 0xf6, 0x55, 0x8a, 0xed, 0x13, 0xa3, 0x4f,
0x65, 0x6e, 0xee, 0xb1, 0x70, 0x04, 0xcb, 0x55, 0x99, 0xe5, 0xea, 0x46, 0x22, 0x70, 0x8c, 0x30,
0xb8, 0x53, 0x06, 0xc0, 0x90, 0xe5, 0xea, 0xd3, 0xca, 0x15, 0xd5, 0x94, 0x00, 0x12, 0x41, 0x13,
0x88, 0x8c, 0xed, 0x05, 0xbc, 0x70, 0x45, 0x87, 0xe7, 0xaf, 0xce, 0x96, 0xab, 0x10, 0xcb, 0xd5,
0xb2, 0x9f, 0x17, 0x30, 0x66, 0x79, 0x1e, 0xe1, 0xcb, 0xdd, 0xc6, 0x46, 0xce, 0x9b, 0xbc, 0xf3,
0x89, 0x31, 0x66, 0xd3, 0x7f, 0xd4, 0x72, 0xd5, 0xca, 0x72, 0xf5, 0xba, 0x24, 0x49, 0x92, 0xf4,
0x05, 0x52, 0x0d, 0x4e, 0x68, 0xa4, 0x9a, 0xa9, 0x29, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
0x44, 0xae, 0x42, 0x60, 0x82
};
// Generated by png2h.py from sprites100.png - do not edit
#pragma once
#define ATLAS_WIDTH 1233
#define ATLAS_HEIGHT 68
// Index 0 is transparent
static const unsigned DINO_PALETTE[5] = {
0x00000000, 0x00535353, 0x00F7F7F7, 0x00FFFFFF, 0x00DADADA,
};
static const unsigned char SPRITE_ATLAS[ATLAS_WIDTH * ATLAS_HEIGHT] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,2,1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,2,1,1,1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,2,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,3,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,2,0,0,0,0,3,3,0,3,1,1,1,1,1,3,0,0,3,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,2,0,0,0,2,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,3,1,3,0,3,1,1,1,1,1,3,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,2,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,2,0,0,3,1,1,3,3,1,1,1,1,1,3,0,3,1,3,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,2,0,2,1,1,1,2,2,1,1,1,1,1,2,0,0,0,0,0,3,1,1,1,3,3,1,1,1,1,1,3,0,3,1,3,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,0,0,0,0,0,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,0,0,2,0,0,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,1,1,1,1,1,2,2,1,1,1,2,0,0,2,0,0,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,0,0,2,0,0,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,0,2,1,2,0,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,0,2,1,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,2,1,1,1,1,1,2,2,1,1,1,2,0,2,1,2,0,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,0,2,1,2,0,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,2,2,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2,2,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,4,4,0,4,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,2,1,1,2,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,2,0,0,0,2,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,4,4,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,3,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,0,2,2,2,0,0,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,2,2,2,0,0,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,2,2,2,0,0,0,2,1,1,1,1,1,1,1,2,0,0,2,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,0,2,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,0,3,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,3,3,1,1,1,1,1,3,3,1,1,1,3,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,0,0,3,1,1,1,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,1,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,2,2,0,0,2,1,1,1,1,1,2,0,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,0,0,0,0,3,3,3,1,1,1,1,1,3,3,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,3,3,1,1,1,1,1,1,1,1,1,3,3,1,1,1,3,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,2,0,2,1,1,1,1,1,2,2,2,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,0,0,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,3,1,1,1,1,1,1,1,1,1,1,3,2,1,1,1,2,2,1,1,1,1,1,1,1,1,2,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,0,0,3,1,1,1,1,1,1,1,1,1,1,1,1,1,3,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,0,2,2,1,1,2,2,0,0,0,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,2,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,2,0,0,0,0,0,0,0,0,3,1,1,1,1,1,1,1,1,1,3,0,2,1,1,1,2,2,1,1,1,1,1,2,2,2,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,0,0,0,3,3,3,1,1,1,1,1,1,1,1,1,3,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,2,0,0,0,2,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,1,1,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,1,1,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,
0,0,2,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,2,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,2,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,1,1,1,3,0,0,2,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,2,1,1,1,2,2,1,1,1,1,1,2,2,1,1,1,2,0,0,0,0,0,3,1,1,1,1,1,1,1,1,3,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,2,0,0,0,2,1,2,0,0,0,2,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,1,1,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,2,0,0,2,2,1,1,2,2,0,0,0,0,0,0,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,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,0,0,0,2,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,3,3,0,0,0,0,2,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,2,2,1,1,1,2,0,0,0,0,0,3,1,1,1,1,1,3,3,3,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,2,2,2,2,0,0,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,1,1,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,3,3,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,2,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,2,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,2,2,1,1,1,2,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,2,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,1,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,3,3,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,1,1,1,1,1,1,3,3,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,0,0,0,
0,0,2,1,1,1,1,1,1,1,1,1,1,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,0,0,2,2,1,1,1,1,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,0,2,2,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,2,0,0,0,0,0,3,1,1,1,1,1,3,0,0,0,0,0,0,0,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,2,1,1,1,1,1,2,0,2,1,1,1,1,1,1,1,2,0,2,1,1,1,1,2,2,1,1,1,1,2,2,1,1,1,1,1,2,0,0,0,0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,0,2,1,1,1,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,