From 045b84f82cd0f6fc96d6e3834b68d06dbd7c6e63 Mon Sep 17 00:00:00 2001 From: irori Date: Thu, 21 Dec 2023 22:04:18 +0900 Subject: [PATCH] Use libblokusduo as a submodule dependency --- .gitmodules | 3 + backend/Makefile | 27 - backend/board.cpp | 484 -------- backend/board.h | 100 -- backend/hm5move.cpp | 58 - backend/opening.cpp | 268 ----- backend/opening.h | 13 - backend/opening_book | 1861 ----------------------------- backend/piece.h | 32 - backend/piece.rb | 250 ---- backend/probcut.h | 28 - backend/probcut.tab.c | 250 ---- backend/search.cpp | 479 -------- backend/search.h | 17 - backend/str.h | 34 - docs/hm5move.js | 2 +- docs/hm5move.wasm | Bin 73274 -> 80384 bytes wasm/CMakeLists.txt | 15 + wasm/blokusduo | 1 + wasm/hm5move.cpp | 54 + {backend => wasm}/hm5move_post.js | 0 21 files changed, 74 insertions(+), 3902 deletions(-) create mode 100644 .gitmodules delete mode 100644 backend/Makefile delete mode 100644 backend/board.cpp delete mode 100644 backend/board.h delete mode 100644 backend/hm5move.cpp delete mode 100644 backend/opening.cpp delete mode 100644 backend/opening.h delete mode 100644 backend/opening_book delete mode 100644 backend/piece.h delete mode 100755 backend/piece.rb delete mode 100644 backend/probcut.h delete mode 100644 backend/probcut.tab.c delete mode 100644 backend/search.cpp delete mode 100644 backend/search.h delete mode 100644 backend/str.h create mode 100644 wasm/CMakeLists.txt create mode 160000 wasm/blokusduo create mode 100644 wasm/hm5move.cpp rename {backend => wasm}/hm5move_post.js (100%) diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..773b554 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wasm/blokusduo"] + path = wasm/blokusduo + url = https://github.com/irori/blokusduo.git diff --git a/backend/Makefile b/backend/Makefile deleted file mode 100644 index 8bc340c..0000000 --- a/backend/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -*- Makefile -*- for emscripten - -CXX = em++ -CXXFLAGS = -Wall -Oz -#CXXFLAGS = -g -#CXXFLAGS = -pg -O -g - -EMFLAGS = -s ENVIRONMENT=worker \ - -s EXPORTED_FUNCTIONS=_hm5move,_getVisitedNodes \ - -s EXPORTED_RUNTIME_METHODS=cwrap - -OBJS = hm5move.o search.o board.o opening.o piece.o - -../docs/hm5move.js: $(OBJS) hm5move_post.js - $(CXX) $(CXXFLAGS) $(EMFLAGS) --post-js hm5move_post.js -o $@ $(OBJS) - -piece.cpp: piece.rb - ruby piece.rb >piece.cpp - -hm5move.o: hm5move.cpp board.h search.h opening.h str.h -search.o: search.cpp board.h search.h probcut.h probcut.tab.c -board.o: board.cpp piece.h opening.h board.h str.h -opening.o: opening.cpp opening.h -piece.o: piece.cpp piece.h - -clean: - rm -f *.o hm5move.bc ../docs/hm5move.js* diff --git a/backend/board.cpp b/backend/board.cpp deleted file mode 100644 index 4ba5306..0000000 --- a/backend/board.cpp +++ /dev/null @@ -1,484 +0,0 @@ -#include -#include -#include -#include "board.h" -#include "opening.h" -#include "str.h" - -#define VIOLET_MASK 0x07 -#define ORANGE_MASK 0x70 -#define VIOLET_EDGE 0x01 -#define ORANGE_EDGE 0x10 -#define VIOLET_SIDE 0x02 -#define ORANGE_SIDE 0x20 -#define VIOLET_BLOCK 0x04 -#define ORANGE_BLOCK 0x40 -#define EFFECT 0x08 - -struct Edge { - int x, y, direction; -}; - -Move::Move(const char* fourcc) -{ - if (fourcc[0] == '-') - m_ = 0xffff; - else { - int xy; - sscanf(fourcc, "%2X", &xy); - m_ = xy - 0x11 | - (('u' - tolower(fourcc[2])) & 0x1f) << 11 | - (fourcc[3] - '0') << 8; - } -} - -const char* Move::fourcc() const -{ - static char buf[5]; - if (is_pass()) - strcpy(buf, "----"); - else - sprintf(buf, "%2X%c%d", - (m_ & 0xff) + 0x11, 'u' - block_id(), direction()); - return buf; -} - -Move Move::mirror() const -{ - if (is_pass()) - return PASS; - int d = (direction() + (direction() & 1 ? 5 : 3)) & 7; - Rotation* rot = &block_set[block_id()]->rotations[d]; - int new_x = y() + rot->offset_x; - int new_y = x() + rot->offset_y; - return Move(new_x, new_y, rot->piece->id); -} - -Board::Board() -{ - memset(square, 0, sizeof(square)); - at(START1X, START1Y) = VIOLET_EDGE; - at(START2X, START2Y) = ORANGE_EDGE; - - turn_ = 0; - memset(block_info, 0, sizeof(block_info)); -} - -bool Board::is_valid_move(Move move) -{ - if (move.is_pass()) - return true; - - if (blocks()[move.block_id()]) - return false; - - Rotation* rot = &block_set[move.block_id()]->rotations[move.direction()]; - int px = move.x() + rot->offset_x; - int py = move.y() + rot->offset_y; - Piece *piece = rot->piece; - - if (px + piece->minx < 0 || px + piece->maxx >= XSIZE || - py + piece->miny < 0 || py + piece->maxy >= YSIZE || - !is_movable(px, py, piece)) - return false; - - for (int i = 0; i < piece->size; i++) { - int x = px + piece->coords[i].x; - int y = py + piece->coords[i].y; - if (at(x, y) & (is_violet() ? VIOLET_EDGE : ORANGE_EDGE)) - return true; - } - return false; -} - -void Board::do_move(Move move) -{ - if (move.is_pass()) { - do_pass(); - return; - } - - Rotation* rot = &block_set[move.block_id()]->rotations[move.direction()]; - int px = move.x() + rot->offset_x; - int py = move.y() + rot->offset_y; - Piece *piece = rot->piece; - - unsigned char block = is_violet() ? VIOLET_BLOCK : ORANGE_BLOCK; - unsigned char side_bit = is_violet() ? VIOLET_SIDE : ORANGE_SIDE; - unsigned char edge_bit = is_violet() ? VIOLET_EDGE : ORANGE_EDGE; - - for (int i = 0; i < piece->size; i++) { - int x = px + piece->coords[i].x; - int y = py + piece->coords[i].y; - at(x, y) |= block; - if (in_bounds(x-1, y)) at(x-1, y) |= side_bit; - if (in_bounds(x, y-1)) at(x, y-1) |= side_bit; - if (in_bounds(x+1, y)) at(x+1, y) |= side_bit; - if (in_bounds(x, y+1)) at(x, y+1) |= side_bit; - if (in_bounds(x-1,y-1)) at(x-1,y-1) |= edge_bit; - if (in_bounds(x+1,y-1)) at(x+1,y-1) |= edge_bit; - if (in_bounds(x-1,y+1)) at(x-1,y+1) |= edge_bit; - if (in_bounds(x+1,y+1)) at(x+1,y+1) |= edge_bit; - } - - int blk = is_violet() ? move.block_id() : move.block_id() + NBLOCK; - block_info[blk] = move.xy() + 0x11; - block_info[NBLOCK*2 + move.block_id()] |= - is_violet() ? move.direction() : move.direction() << 4; - - turn_++; -} - -inline bool Board::move_filter(const Piece *piece) -{ - if (turn() < 8 && piece->size < 5) - return false; - else - return true; -} - -bool Board::is_movable(int px, int py, const Piece *piece) -{ - unsigned char mask = is_violet() ? VIOLET_BLOCK|VIOLET_SIDE|ORANGE_BLOCK - : ORANGE_BLOCK|ORANGE_SIDE|VIOLET_BLOCK; - - for (int i = 0; i < piece->size; i++) { - int x = px + piece->coords[i].x; - int y = py + piece->coords[i].y; - if (at(x, y) & mask) - return false; - } - return true; -} - -class MoveCollector : public MovableVisitor { -public: - MoveCollector(Move* a) : movables(a), nmove(0) {} - virtual bool visit_move(Move m) { - movables[nmove++] = m; - return true; - } - Move* movables; - int nmove; -}; - -int Board::movables(Move* movables) -{ - MoveCollector collector(movables); - each_movable(&collector); - return collector.nmove; -} - -bool Board::each_movable(MovableVisitor* visitor) -{ - if (turn() < 2) { - const unsigned short *move = (turn() == 0) ? - violet_first_moves : orange_first_moves; - for (; *move; move++) { - Move m(*move); - if (move_filter(block_set[m.block_id()]-> - rotations[m.direction()].piece)) - { - if (!visitor->visit_move(m)) - return false; - } - } - return true; - } - - Edge edges[100], *pedge; - { - unsigned char edge_mask = is_violet() - ? VIOLET_MASK | ORANGE_BLOCK - : ORANGE_MASK | VIOLET_BLOCK; - unsigned char edge_bit = is_violet() ? VIOLET_EDGE : ORANGE_EDGE; - unsigned char side_bit = is_violet() ? VIOLET_SIDE : ORANGE_SIDE; - - pedge = edges; - for (int ey = 0; ey < YSIZE; ey++) { - for (int ex = 0; ex < XSIZE; ex++) { - if ((at(ex, ey) & edge_mask) == edge_bit) { - pedge->x = ex; - pedge->y = ey; - pedge->direction = (ey > 0 && at(ex, ey-1) & side_bit) - ? (ex > 0 && (at(ex-1, ey) & side_bit) ? 0 : 1) - : (ex > 0 && (at(ex-1, ey) & side_bit) ? 2 : 3); - pedge++; - } - } - } - pedge->x = -1; - } - - int nmove = 0; - for (int blk = 0; blk < NBLOCK; blk++) { - if (blocks()[blk]) - continue; - Block* block = block_set[blk]; - for (Piece **variation = block->variations; *variation; variation++) { - if (!move_filter(*variation)) - continue; - short checked[YSIZE]; - memset(checked, 0, sizeof(checked)); - for (pedge = edges; pedge->x >= 0; pedge++) { - for (int i = 0; i < (*variation)->nedge[pedge->direction]; i++) { - int x = pedge->x - (*variation)->edges[pedge->direction][i].x; - int y = pedge->y - (*variation)->edges[pedge->direction][i].y; - if (y + (*variation)->miny < 0 || - y + (*variation)->maxy >= YSIZE || - x + (*variation)->minx < 0 || - x + (*variation)->maxx >= XSIZE || - (checked[y] & 1 << x)) - continue; - checked[y] |= 1 << x; - if (is_movable(x, y, *variation)) { - if (!visitor->visit_move(Move(x, y, (*variation)->id))) - return false; - nmove++; - } - } - } - } - } - if (nmove == 0) - return visitor->visit_move(PASS); - - return true; -} - -int Board::calc_score(unsigned char* blks_vec) -{ - int score = 0; - - for (int i = 0; i < NBLOCK; i++) { - if (blks_vec[i]) - score += block_set[i]->size; - } - return score; -} - -int Board::eval_blocks() -{ - const int table[NBLOCK] = { - 16,16,16,16,16,16,16,16,16,16,16,16, 10,10,10,10,10, 6,6, 4, 2 - }; - int score = 0; - - for (int i = 0; i < NBLOCK; i++) { - if (block_info[i] == 0) - score -= table[i]; - if (block_info[NBLOCK + i] == 0) - score += table[i]; - } - return score; -} - -int Board::eval_effect() -{ - unsigned char b[16*15]; - unsigned char *edges[2][YSIZE*XSIZE], **pedge, **pnew_edge; - int score = 0; - - for (int x = 0; x <= XSIZE; x++) - b[x] = VIOLET_BLOCK|ORANGE_BLOCK; - for (int y = 0; y <= YSIZE; y++) - b[y*15+XSIZE] = VIOLET_BLOCK|ORANGE_BLOCK; - for (int x = 0; x <= XSIZE; x++) - b[225+x] = VIOLET_BLOCK|ORANGE_BLOCK; - - for (int player = 0; player < 2; player++) { - const unsigned char mask[2] = { VIOLET_MASK|ORANGE_BLOCK, - ORANGE_MASK|VIOLET_BLOCK }; - const unsigned char edge[2] = { VIOLET_EDGE, ORANGE_EDGE }; - - pedge = edges[0]; - for (int y = 0; y < YSIZE; y++) { - for (int x = 0; x < XSIZE; x++) { - b[(y+1)*15+x] = at(x,y) & mask[player]; - if (b[(y+1)*15+x] == edge[player]) { - *pedge++ = &b[(y+1)*15+x]; - score++; - } - } - } - *pedge = NULL; - - pedge = edges[0]; - pnew_edge = edges[1]; - while (*pedge) { - unsigned char* pos = *pedge++; - if (pos[-15] == 0) { - pos[-15] = 1; - *pnew_edge++ = pos-15; - score++; - } - if (pos[-1] == 0) { - pos[-1] = 1; - *pnew_edge++ = pos-1; - score++; - } - if (pos[1] == 0) { - pos[1] = 1; - *pnew_edge++ = pos+1; - score++; - } - if (pos[15] == 0) { - pos[15] = 1; - *pnew_edge++ = pos+15; - score++; - } - } - *pnew_edge = NULL; - - pedge = edges[1]; - pnew_edge = edges[0]; - while (*pedge) { - unsigned char* pos = *pedge++; - if (pos[-15] == 0) { - pos[-15] = 1; - *pnew_edge++ = pos-15; - score++; - } - if (pos[-1] == 0) { - pos[-1] = 1; - *pnew_edge++ = pos-1; - score++; - } - if (pos[1] == 0) { - pos[1] = 1; - *pnew_edge++ = pos+1; - score++; - } - if (pos[15] == 0) { - pos[15] = 1; - *pnew_edge++ = pos+15; - score++; - } - } - *pnew_edge = NULL; - - pedge = edges[0]; - while (*pedge) { - unsigned char* pos = *pedge++; - if (pos[-15] == 0) { - pos[-15] = 1; - score++; - } - if (pos[-1] == 0) { - pos[-1] = 1; - score++; - } - if (pos[1] == 0) { - pos[1] = 1; - score++; - } - if (pos[15] == 0) { - pos[15] = 1; - score++; - } - } - - score = -score; - } - return score; -} - -void Board::show() -{ - unsigned char b[2][YSIZE+2][XSIZE+1]; - int edges1[YSIZE*XSIZE], *pedge; - int edges2[YSIZE*XSIZE], *pnew_edge; - - for (int player = 0; player < 2; player++) { - for (int x = 0; x <= XSIZE; x++) - b[player][0][x] = VIOLET_BLOCK|ORANGE_BLOCK; - for (int y = 0; y <= YSIZE; y++) - b[player][y][XSIZE] = VIOLET_BLOCK|ORANGE_BLOCK; - for (int x = 0; x <= XSIZE; x++) - b[player][YSIZE+1][x] = VIOLET_BLOCK|ORANGE_BLOCK; - - unsigned char mask = player == 0 ? (VIOLET_MASK|ORANGE_BLOCK) - : (ORANGE_MASK|VIOLET_BLOCK); - unsigned char edge = player == 0 ? VIOLET_EDGE : ORANGE_EDGE; - - pedge = edges1; - for (int y = 0; y < YSIZE; y++) { - for (int x = 0; x < XSIZE; x++) { - b[player][y+1][x] = at(x,y) & mask; - if (b[player][y+1][x] == edge) { - *pedge++ = x; - *pedge++ = y+1; - } - } - } - *pedge = -1; - - for (int iterate = 0; iterate < 3; iterate++) { - pnew_edge = (iterate % 2) ? edges1 : edges2; - pedge = (iterate % 2) ? edges2 : edges1; - while (*pedge >= 0) { - int x = *pedge++; - int y = *pedge++; - if (b[player][y-1][x] == 0) { - b[player][y-1][x] = EFFECT; - *pnew_edge++ = x; - *pnew_edge++ = y-1; - } - if (b[player][y][x-1] == 0) { - b[player][y][x-1] = EFFECT; - *pnew_edge++ = x-1; - *pnew_edge++ = y; - } - if (b[player][y][x+1] == 0) { - b[player][y][x+1] = EFFECT; - *pnew_edge++ = x+1; - *pnew_edge++ = y; - } - if (b[player][y+1][x] == 0) { - b[player][y+1][x] = EFFECT; - *pnew_edge++ = x; - *pnew_edge++ = y+1; - } - } - *pnew_edge = -1; - } - } - puts(" " STR_BOARD_HEADER); - puts(" " STR_FRAME_TOP); - for (int y = 0; y < YSIZE; y++) { - printf(" %X", y+1); - for (int color = 0; color <= 1; color++) { - printf(STR_FRAME_SIDE); - for (int x = 0; x < XSIZE; x++) { - unsigned char c = at(x, y); - if (c & (color ? ORANGE_BLOCK : VIOLET_BLOCK)) - printf(STR_VIOLET_BLOCK); - else if (c & (color ? VIOLET_BLOCK : ORANGE_BLOCK)) - printf(STR_ORANGE_BLOCK); - else if (c & (color ? ORANGE_SIDE : VIOLET_SIDE)) - printf(STR_BLANK); - else if (c & (color ? ORANGE_EDGE : VIOLET_EDGE)) - printf(STR_EDGE); - else if (b[color][y+1][x] == EFFECT) - printf(STR_EFFECT); - else - printf(STR_BLANK); - } - } - printf(STR_FRAME_SIDE "\n"); - } - puts(" " STR_FRAME_BOTTOM); - - printf(" violet:"); - for (int b = NBLOCK-1; b >= 0; b--) { - if (block_info[b] == 0) - printf(" %c", block_set[b]->name()); - } - printf(" (%d)\n", violet_score()); - printf(" orange:"); - for (int b = NBLOCK-1; b >= 0; b--) { - if (block_info[b + NBLOCK] == 0) - printf(" %c", block_set[b]->name()); - } - printf(" (%d)\n", orange_score()); -} diff --git a/backend/board.h b/backend/board.h deleted file mode 100644 index 4814c3b..0000000 --- a/backend/board.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef BOARD_H_ -#define BOARD_H_ - -#include -#include "piece.h" - -class Move { -public: - Move() {} - Move(unsigned short m) : m_(m) {}; - Move(const char* fourcc); - Move(int x, int y, int piece_id) : m_(x << 4 | y | piece_id << 8) {} - int x() const { return m_ >>4 & 0xf; } - int y() const { return m_ & 0xf; } - int piece_id() const { return m_ >> 8; } - int block_id() const { return m_ >> 11; } - int direction() const { return m_ >> 8 & 0x7; } - bool is_pass() const { return m_ == 0xffff; } - const char* fourcc() const; - bool operator<(const Move& rhs) const { return m_ < rhs.m_; } - bool operator==(const Move& rhs) const { return m_ == rhs.m_; } - unsigned char xy() const { return m_ & 0xff; } - unsigned short to_i() const { return m_; } - Move mirror() const; -private: - unsigned short m_; -}; - -static Move INVALID_MOVE(0xfffe); -static Move PASS(0xffff); - -class MovableVisitor { -public: - virtual ~MovableVisitor() {} - virtual bool visit_move(Move m) = 0; -}; - -class Board { -public: - static const int NBLOCK = 21; - static const int XSIZE = 14; - static const int YSIZE = 14; - static const int START1X = 4; - static const int START1Y = 4; - static const int START2X = 9; - static const int START2Y = 9; - static const int KEY_SIZE = NBLOCK*2 + NBLOCK; - static bool in_bounds(int x, int y) { - return (x >= 0 && y >= 0 && x < XSIZE && y < YSIZE); - } - Board(); - unsigned char& at(int x, int y) { return square[y][x]; } - int turn() { return turn_; } - bool is_violet() { return (turn_ & 1) == 0; } - bool is_valid_move(Move move); - void do_move(Move move); - void do_pass() { turn_++; } - int movables(Move* movables); - bool each_movable(MovableVisitor* visitor); - Board child(Move move) { - Board c(*this); - c.do_move(move); - return c; - } - int evaluate() { return eval_blocks() + eval_effect(); } - int nega_eval() { return is_violet() ? evaluate() : -evaluate(); } - int violet_score() { return calc_score(block_info); } - int orange_score() { return calc_score(block_info + NBLOCK); } - int nega_score() { - int b = violet_score(), w = orange_score(); - return is_violet() ? b - w : w - b; - } - void key(char* buf) { memcpy(buf, block_info, KEY_SIZE); } - void show(); -protected: - unsigned char square[YSIZE][XSIZE]; - int turn_; - unsigned char block_info[KEY_SIZE]; - - const unsigned char* blocks() { - return is_violet() ? block_info : block_info + NBLOCK; - } - bool move_filter(const Piece *piece); - bool is_movable(int px, int py, const Piece *piece); - int calc_score(unsigned char* blks_vec); - int eval_blocks(); - int eval_effect(); -}; - -class BoardMapKey { -public: - BoardMapKey(Board& b) { b.key(b_); } - bool operator<(const BoardMapKey& rhs) const { - return memcmp(b_, rhs.b_, sizeof(b_)) < 0; - } -private: - char b_[Board::KEY_SIZE]; -}; - -#endif // BOARD_H_ diff --git a/backend/hm5move.cpp b/backend/hm5move.cpp deleted file mode 100644 index 22c5e37..0000000 --- a/backend/hm5move.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include "board.h" -#include "search.h" -#include "opening.h" - -extern "C" const char* hm5move(const char* pathstr, int max_depth, int time_limit); -extern "C" int getVisitedNodes(); - -Move com_move(Board* b, int max_depth, int time_ms) -{ - Move move; - int score = 100; - quiet = true; - - move = opening_move(b); - if (move == INVALID_MOVE) { - SearchResult r; - if (b->turn() < 25) - r = search_negascout(b, max_depth, time_ms / 2, time_ms); - else if (b->turn() < 27) - r = wld(b, 1000); - else - r = perfect(b); - move = r.first; - score = r.second; - } - - return move; -} - -const char* hm5move(const char* path, int max_depth, int time_limit) -{ - static bool initialized = false; - if (!initialized) { - srand(time(NULL)); - initialized = true; - } - - Board b; - while (*path) { - Move m(path); - path += 4; - if (*path == '/') - path++; - if (m == INVALID_MOVE || !b.is_valid_move(m)) - return "XXXX invalid move "; - b.do_move(m); - } - visited_nodes = 0; - Move m = com_move(&b, max_depth, time_limit); - return m.fourcc(); -} - -int getVisitedNodes() -{ - return visited_nodes; -} diff --git a/backend/opening.cpp b/backend/opening.cpp deleted file mode 100644 index c7c0ee6..0000000 --- a/backend/opening.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include "board.h" -#include "opening.h" - -#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0])) - -// All possible first moves for Violet -const unsigned short violet_first_moves[] = { - 0x0044, 0x0034, 0x0043, 0x0054, 0x0045, 0x0855, 0x0854, 0x0844, - 0x0834, 0x0843, 0x0935, 0x0934, 0x0944, 0x0954, 0x0943, 0x0a35, - 0x0a45, 0x0a44, 0x0a43, 0x0a54, 0x0b55, 0x0b45, 0x0b44, 0x0b43, - 0x0b34, 0x0c33, 0x0c34, 0x0c44, 0x0c54, 0x0c45, 0x0d53, 0x0d54, - 0x0d44, 0x0d34, 0x0d45, 0x0e53, 0x0e43, 0x0e44, 0x0e45, 0x0e34, - 0x0f33, 0x0f43, 0x0f44, 0x0f45, 0x0f54, 0x1044, 0x1034, 0x1033, - 0x1054, 0x1055, 0x1144, 0x1154, 0x1153, 0x1134, 0x1135, 0x1244, - 0x1243, 0x1253, 0x1245, 0x1235, 0x1344, 0x1343, 0x1333, 0x1345, - 0x1355, 0x1844, 0x1834, 0x1833, 0x1845, 0x1855, 0x1944, 0x1954, - 0x1953, 0x1945, 0x1935, 0x1a44, 0x1a43, 0x1a53, 0x1a34, 0x1a35, - 0x1b44, 0x1b43, 0x1b33, 0x1b54, 0x1b55, 0x2044, 0x2034, 0x2024, - 0x2045, 0x2046, 0x2144, 0x2154, 0x2164, 0x2145, 0x2146, 0x2244, - 0x2243, 0x2242, 0x2234, 0x2224, 0x2344, 0x2343, 0x2342, 0x2354, - 0x2364, 0x2844, 0x2845, 0x2843, 0x2853, 0x2833, 0x2a44, 0x2a34, - 0x2a54, 0x2a55, 0x2a53, 0x2b44, 0x2b54, 0x2b34, 0x2b35, 0x2b33, - 0x2c44, 0x2c43, 0x2c45, 0x2c35, 0x2c55, 0x3045, 0x3044, 0x3034, - 0x3043, 0x3042, 0x3145, 0x3144, 0x3154, 0x3143, 0x3142, 0x3234, - 0x3244, 0x3243, 0x3254, 0x3264, 0x3354, 0x3344, 0x3343, 0x3334, - 0x3324, 0x3443, 0x3444, 0x3454, 0x3445, 0x3446, 0x3543, 0x3544, - 0x3534, 0x3545, 0x3546, 0x3654, 0x3644, 0x3645, 0x3634, 0x3624, - 0x3734, 0x3744, 0x3745, 0x3754, 0x3764, 0x3844, 0x3843, 0x3853, - 0x3845, 0x3855, 0x3944, 0x3943, 0x3933, 0x3945, 0x3935, 0x3a44, - 0x3a54, 0x3a55, 0x3a34, 0x3a35, 0x3e44, 0x3e34, 0x3e33, 0x3e54, - 0x3e53, 0x4045, 0x4054, 0x4044, 0x4053, 0x4043, 0x4145, 0x4134, - 0x4144, 0x4133, 0x4143, 0x4234, 0x4245, 0x4244, 0x4255, 0x4254, - 0x4354, 0x4345, 0x4344, 0x4335, 0x4334, 0x4443, 0x4434, 0x4444, - 0x4435, 0x4445, 0x4543, 0x4554, 0x4544, 0x4555, 0x4545, 0x4654, - 0x4643, 0x4644, 0x4633, 0x4634, 0x4734, 0x4743, 0x4744, 0x4753, - 0x4754, 0x4846, 0x4845, 0x4844, 0x4854, 0x4853, 0x4946, 0x4945, - 0x4944, 0x4934, 0x4933, 0x4a24, 0x4a34, 0x4a44, 0x4a45, 0x4a55, - 0x4b64, 0x4b54, 0x4b44, 0x4b45, 0x4b35, 0x4c42, 0x4c43, 0x4c44, - 0x4c34, 0x4c35, 0x4d42, 0x4d43, 0x4d44, 0x4d54, 0x4d55, 0x4e64, - 0x4e54, 0x4e44, 0x4e43, 0x4e33, 0x4f24, 0x4f34, 0x4f44, 0x4f43, - 0x4f53, 0x5044, 0x5043, 0x5046, 0x5045, 0x5053, 0x5144, 0x5143, - 0x5146, 0x5145, 0x5133, 0x5244, 0x5254, 0x5224, 0x5234, 0x5255, - 0x5344, 0x5334, 0x5364, 0x5354, 0x5335, 0x5444, 0x5445, 0x5442, - 0x5443, 0x5435, 0x5544, 0x5545, 0x5542, 0x5543, 0x5555, 0x5644, - 0x5634, 0x5664, 0x5654, 0x5633, 0x5744, 0x5754, 0x5724, 0x5734, - 0x5753, 0x5844, 0x5843, 0x5842, 0x5845, 0x5846, 0x5a44, 0x5a54, - 0x5a64, 0x5a34, 0x5a24, 0x6054, 0x6044, 0x6043, 0x6033, 0x6134, - 0x6144, 0x6143, 0x6153, 0x6245, 0x6244, 0x6254, 0x6253, 0x6345, - 0x6344, 0x6334, 0x6333, 0x6844, 0x6834, 0x6843, 0x6833, 0x7044, - 0x7034, 0x7043, 0x7045, 0x7144, 0x7154, 0x7143, 0x7145, 0x7244, - 0x7243, 0x7254, 0x7234, 0x7644, 0x7645, 0x7634, 0x7654, 0x7844, - 0x7845, 0x7843, 0x7853, 0x7944, 0x7945, 0x7943, 0x7933, 0x7a44, - 0x7a34, 0x7a54, 0x7a55, 0x7b44, 0x7b54, 0x7b34, 0x7b35, 0x7c44, - 0x7c43, 0x7c45, 0x7c35, 0x7d44, 0x7d43, 0x7d45, 0x7d55, 0x7e44, - 0x7e54, 0x7e34, 0x7e33, 0x7f44, 0x7f34, 0x7f54, 0x7f53, 0x8044, - 0x8043, 0x8042, 0x8045, 0x8244, 0x8254, 0x8264, 0x8234, 0x8844, - 0x8834, 0x8845, 0x8944, 0x8954, 0x8945, 0x8a44, 0x8a43, 0x8a34, - 0x8b44, 0x8b43, 0x8b54, 0x9044, 0x9043, 0x9045, 0x9244, 0x9254, - 0x9234, 0x9844, 0x9843, 0x9a44, 0x9a54, 0xa044, 0 -}; - -// All possible first moves for Orange -const unsigned short orange_first_moves[] = { - 0x0099, 0x0089, 0x0098, 0x00a9, 0x009a, 0x08aa, 0x08a9, 0x0899, - 0x0889, 0x0898, 0x098a, 0x0989, 0x0999, 0x09a9, 0x0998, 0x0a8a, - 0x0a9a, 0x0a99, 0x0a98, 0x0aa9, 0x0baa, 0x0b9a, 0x0b99, 0x0b98, - 0x0b89, 0x0c88, 0x0c89, 0x0c99, 0x0ca9, 0x0c9a, 0x0da8, 0x0da9, - 0x0d99, 0x0d89, 0x0d9a, 0x0ea8, 0x0e98, 0x0e99, 0x0e9a, 0x0e89, - 0x0f88, 0x0f98, 0x0f99, 0x0f9a, 0x0fa9, 0x1099, 0x1089, 0x1088, - 0x10a9, 0x10aa, 0x1199, 0x11a9, 0x11a8, 0x1189, 0x118a, 0x1299, - 0x1298, 0x12a8, 0x129a, 0x128a, 0x1399, 0x1398, 0x1388, 0x139a, - 0x13aa, 0x1899, 0x1889, 0x1888, 0x189a, 0x18aa, 0x1999, 0x19a9, - 0x19a8, 0x199a, 0x198a, 0x1a99, 0x1a98, 0x1aa8, 0x1a89, 0x1a8a, - 0x1b99, 0x1b98, 0x1b88, 0x1ba9, 0x1baa, 0x2099, 0x2089, 0x2079, - 0x209a, 0x209b, 0x2199, 0x21a9, 0x21b9, 0x219a, 0x219b, 0x2299, - 0x2298, 0x2297, 0x2289, 0x2279, 0x2399, 0x2398, 0x2397, 0x23a9, - 0x23b9, 0x2899, 0x289a, 0x2898, 0x28a8, 0x2888, 0x2a99, 0x2a89, - 0x2aa9, 0x2aaa, 0x2aa8, 0x2b99, 0x2ba9, 0x2b89, 0x2b8a, 0x2b88, - 0x2c99, 0x2c98, 0x2c9a, 0x2c8a, 0x2caa, 0x309a, 0x3099, 0x3089, - 0x3098, 0x3097, 0x319a, 0x3199, 0x31a9, 0x3198, 0x3197, 0x3289, - 0x3299, 0x3298, 0x32a9, 0x32b9, 0x33a9, 0x3399, 0x3398, 0x3389, - 0x3379, 0x3498, 0x3499, 0x34a9, 0x349a, 0x349b, 0x3598, 0x3599, - 0x3589, 0x359a, 0x359b, 0x36a9, 0x3699, 0x369a, 0x3689, 0x3679, - 0x3789, 0x3799, 0x379a, 0x37a9, 0x37b9, 0x3899, 0x3898, 0x38a8, - 0x389a, 0x38aa, 0x3999, 0x3998, 0x3988, 0x399a, 0x398a, 0x3a99, - 0x3aa9, 0x3aaa, 0x3a89, 0x3a8a, 0x3e99, 0x3e89, 0x3e88, 0x3ea9, - 0x3ea8, 0x409a, 0x40a9, 0x4099, 0x40a8, 0x4098, 0x419a, 0x4189, - 0x4199, 0x4188, 0x4198, 0x4289, 0x429a, 0x4299, 0x42aa, 0x42a9, - 0x43a9, 0x439a, 0x4399, 0x438a, 0x4389, 0x4498, 0x4489, 0x4499, - 0x448a, 0x449a, 0x4598, 0x45a9, 0x4599, 0x45aa, 0x459a, 0x46a9, - 0x4698, 0x4699, 0x4688, 0x4689, 0x4789, 0x4798, 0x4799, 0x47a8, - 0x47a9, 0x489b, 0x489a, 0x4899, 0x48a9, 0x48a8, 0x499b, 0x499a, - 0x4999, 0x4989, 0x4988, 0x4a79, 0x4a89, 0x4a99, 0x4a9a, 0x4aaa, - 0x4bb9, 0x4ba9, 0x4b99, 0x4b9a, 0x4b8a, 0x4c97, 0x4c98, 0x4c99, - 0x4c89, 0x4c8a, 0x4d97, 0x4d98, 0x4d99, 0x4da9, 0x4daa, 0x4eb9, - 0x4ea9, 0x4e99, 0x4e98, 0x4e88, 0x4f79, 0x4f89, 0x4f99, 0x4f98, - 0x4fa8, 0x5099, 0x5098, 0x509b, 0x509a, 0x50a8, 0x5199, 0x5198, - 0x519b, 0x519a, 0x5188, 0x5299, 0x52a9, 0x5279, 0x5289, 0x52aa, - 0x5399, 0x5389, 0x53b9, 0x53a9, 0x538a, 0x5499, 0x549a, 0x5497, - 0x5498, 0x548a, 0x5599, 0x559a, 0x5597, 0x5598, 0x55aa, 0x5699, - 0x5689, 0x56b9, 0x56a9, 0x5688, 0x5799, 0x57a9, 0x5779, 0x5789, - 0x57a8, 0x5899, 0x5898, 0x5897, 0x589a, 0x589b, 0x5a99, 0x5aa9, - 0x5ab9, 0x5a89, 0x5a79, 0x60a9, 0x6099, 0x6098, 0x6088, 0x6189, - 0x6199, 0x6198, 0x61a8, 0x629a, 0x6299, 0x62a9, 0x62a8, 0x639a, - 0x6399, 0x6389, 0x6388, 0x6899, 0x6889, 0x6898, 0x6888, 0x7099, - 0x7089, 0x7098, 0x709a, 0x7199, 0x71a9, 0x7198, 0x719a, 0x7299, - 0x7298, 0x72a9, 0x7289, 0x7699, 0x769a, 0x7689, 0x76a9, 0x7899, - 0x789a, 0x7898, 0x78a8, 0x7999, 0x799a, 0x7998, 0x7988, 0x7a99, - 0x7a89, 0x7aa9, 0x7aaa, 0x7b99, 0x7ba9, 0x7b89, 0x7b8a, 0x7c99, - 0x7c98, 0x7c9a, 0x7c8a, 0x7d99, 0x7d98, 0x7d9a, 0x7daa, 0x7e99, - 0x7ea9, 0x7e89, 0x7e88, 0x7f99, 0x7f89, 0x7fa9, 0x7fa8, 0x8099, - 0x8098, 0x8097, 0x809a, 0x8299, 0x82a9, 0x82b9, 0x8289, 0x8899, - 0x8889, 0x889a, 0x8999, 0x89a9, 0x899a, 0x8a99, 0x8a98, 0x8a89, - 0x8b99, 0x8b98, 0x8ba9, 0x9099, 0x9098, 0x909a, 0x9299, 0x92a9, - 0x9289, 0x9899, 0x9898, 0x9a99, 0x9aa9, 0xa099, 0 -}; - -// Unique first moves of size=5 for Violet -const unsigned short violet_unique_first_moves[] = { - 0x0044, 0x0043, 0x0054, 0x0855, 0x0854, 0x0844, 0x0834, 0x0843, - 0x0a35, 0x0a45, 0x0a44, 0x0a43, 0x0a54, 0x0c33, 0x0c34, 0x0c44, - 0x0c54, 0x0c45, 0x0e53, 0x0e43, 0x0e44, 0x0e45, 0x0e34, 0x1044, - 0x1034, 0x1033, 0x1054, 0x1055, 0x1244, 0x1243, 0x1253, 0x1245, - 0x1235, 0x1844, 0x1834, 0x1833, 0x1845, 0x1855, 0x1944, 0x1954, - 0x1953, 0x1a44, 0x1a43, 0x1a53, 0x2044, 0x2034, 0x2024, 0x2045, - 0x2046, 0x2144, 0x2154, 0x2164, 0x2244, 0x2243, 0x2242, 0x2844, - 0x2845, 0x2843, 0x2853, 0x2833, 0x2a44, 0x2a34, 0x2a54, 0x2a55, - 0x2a53, 0x3045, 0x3044, 0x3034, 0x3043, 0x3042, 0x3234, 0x3244, - 0x3243, 0x3254, 0x3264, 0x3443, 0x3444, 0x3454, 0x3445, 0x3446, - 0x3654, 0x3644, 0x3645, 0x3634, 0x3624, 0x3844, 0x3843, 0x3853, - 0x3845, 0x3855, 0x3944, 0x3943, 0x3933, 0x3945, 0x3935, 0x4045, - 0x4054, 0x4044, 0x4053, 0x4043, 0x4234, 0x4245, 0x4244, 0x4255, - 0x4254, 0x4443, 0x4434, 0x4444, 0x4435, 0x4445, 0x4654, 0x4643, - 0x4644, 0x4633, 0x4634, 0x4846, 0x4845, 0x4844, 0x4854, 0x4853, - 0x4a24, 0x4a34, 0x4a44, 0x4a45, 0x4a55, 0x4c42, 0x4c43, 0x4c44, - 0x4c34, 0x4c35, 0x4e64, 0x4e54, 0x4e44, 0x4e43, 0x4e33, 0x5044, - 0x5043, 0x5046, 0x5045, 0x5053, 0x5244, 0x5254, 0x5224, 0x5234, - 0x5255, 0x5444, 0x5445, 0x5442, 0x5443, 0x5435, 0x5644, 0x5634, - 0x5664, 0x5654, 0x5633, 0x5844, 0x5843, 0x5842, 0x5845, 0x5846, - 0 -}; - -// Unique first moves of size=5 for Orange -const unsigned short orange_unique_first_moves[] = { - 0x0099, 0x0098, 0x00a9, 0x08aa, 0x08a9, 0x0899, 0x0889, 0x0898, - 0x0a8a, 0x0a9a, 0x0a99, 0x0a98, 0x0aa9, 0x0c88, 0x0c89, 0x0c99, - 0x0ca9, 0x0c9a, 0x0ea8, 0x0e98, 0x0e99, 0x0e9a, 0x0e89, 0x1099, - 0x1089, 0x1088, 0x10a9, 0x10aa, 0x1299, 0x1298, 0x12a8, 0x129a, - 0x128a, 0x1899, 0x1889, 0x1888, 0x189a, 0x18aa, 0x1999, 0x19a9, - 0x19a8, 0x1a99, 0x1a98, 0x1aa8, 0x2099, 0x2089, 0x2079, 0x209a, - 0x209b, 0x2199, 0x21a9, 0x21b9, 0x2299, 0x2298, 0x2297, 0x2899, - 0x289a, 0x2898, 0x28a8, 0x2888, 0x2a99, 0x2a89, 0x2aa9, 0x2aaa, - 0x2aa8, 0x309a, 0x3099, 0x3089, 0x3098, 0x3097, 0x3289, 0x3299, - 0x3298, 0x32a9, 0x32b9, 0x3498, 0x3499, 0x34a9, 0x349a, 0x349b, - 0x36a9, 0x3699, 0x369a, 0x3689, 0x3679, 0x3899, 0x3898, 0x38a8, - 0x389a, 0x38aa, 0x3999, 0x3998, 0x3988, 0x399a, 0x398a, 0x409a, - 0x40a9, 0x4099, 0x40a8, 0x4098, 0x4289, 0x429a, 0x4299, 0x42aa, - 0x42a9, 0x4498, 0x4489, 0x4499, 0x448a, 0x449a, 0x46a9, 0x4698, - 0x4699, 0x4688, 0x4689, 0x489b, 0x489a, 0x4899, 0x48a9, 0x48a8, - 0x4a79, 0x4a89, 0x4a99, 0x4a9a, 0x4aaa, 0x4c97, 0x4c98, 0x4c99, - 0x4c89, 0x4c8a, 0x4eb9, 0x4ea9, 0x4e99, 0x4e98, 0x4e88, 0x5099, - 0x5098, 0x509b, 0x509a, 0x50a8, 0x5299, 0x52a9, 0x5279, 0x5289, - 0x52aa, 0x5499, 0x549a, 0x5497, 0x5498, 0x548a, 0x5699, 0x5689, - 0x56b9, 0x56a9, 0x5688, 0x5899, 0x5898, 0x5897, 0x589a, 0x589b, - 0 -}; - -Move random_move(Board* b) -{ - Move movables[1500]; - int nmove = b->movables(movables); - int i = (int)((rand() / ((double)RAND_MAX+1.0f)) * nmove); - return movables[i]; -} - -static Move first_move() -{ - static const unsigned short moves[] = { - 0x0a45 /*56t2*/, 0x0054 /*65u0*/, 0x2c55 /*66p4*/, 0x3445 /*56o4*/, - 0x0e45 /*56t6*/, 0x3654 /*65o6*/, 0x0855 /*66t0*/, 0x1a53 /*64r2*/, - 0x0a44 /*55t2*/, 0x3264 /*75o2*/ - }; - int i = (int)((rand() / ((double)RAND_MAX+1.0f)) * SIZEOF_ARRAY(moves)); - return moves[i]; -} - -Move opening_move(Board* b) -{ - if (b->turn() == 0) - return first_move(); -// if (b->turn() < 2) -// return random_move(b); - return INVALID_MOVE; -} - -#ifdef MAKE_UNIQUE_MOVE_TABLE -#include -#include - -void make_violet_unique_first_moves() -{ - vector unique_moves; - for (const unsigned short* ptr = violet_first_moves; *ptr; ++ptr) { - Move m(*ptr); - Block* block = block_set[m.block_id()]; - if (block->size < 5) - continue; - switch (block->name()) { - case 'k': case 'l': case 'm': case 'o': case 's': case 't': - if (m.direction() % 2 == 1) - continue; - break; - case 'j': - if (m.direction() != 0) - continue; - break; - case 'n': - if (m.direction() != 0 && m.direction() != 1) - continue; - break; - case 'p': - if (m.direction() != 0 && m.direction() != 2) - continue; - break; - case 'q': - case 'r': - if (m.direction() == 3) - continue; - if ((m.direction() == 1 || m.direction() == 2) && m.x() < m.y()) - continue; - break; - case 'u': - if (m.x() < m.y()) - continue; - break; - } - unique_moves.push_back(m); - } - - vector::const_iterator begin = unique_moves.begin(); - vector::const_iterator end = unique_moves.end(); - for (const unsigned short* ptr = violet_first_moves; *ptr; ++ptr) { - Move m(*ptr); - if (block_set[m.block_id()]->size < 5) - continue; - if (find(begin, end, m) == end && - find(begin, end, m.mirror()) == end) - fprintf(stderr, "not found: %s\n", m.fourcc()); - } - for (vector::const_iterator i = begin; i != end; ++i) { - Move m = *i; - if (find(begin, end, m.mirror()) != end) { - if (m.mirror() == m) - fprintf(stderr, "mirror: 0x%04x\n", m.to_i()); - else - fprintf(stderr, "duplicated: %s\n", m.fourcc()); - } - printf("0x%04x\n", m.to_i()); - } -} - -int main(int argc, char *argv[]) -{ - make_violet_unique_first_moves(); - return 0; -} -#endif diff --git a/backend/opening.h b/backend/opening.h deleted file mode 100644 index aa20dc3..0000000 --- a/backend/opening.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef OPENING_H_ -#define OPENING_H_ - -extern const unsigned short violet_first_moves[]; -extern const unsigned short orange_first_moves[]; -extern const unsigned short violet_unique_first_moves[]; -extern const unsigned short orange_unique_first_moves[]; - -void load_opening_book(const char *fname); -Move opening_move(Board* b); -Move random_move(Board* b); - -#endif // OPENING_H_ diff --git a/backend/opening_book b/backend/opening_book deleted file mode 100644 index a50f3ef..0000000 --- a/backend/opening_book +++ /dev/null @@ -1,1861 +0,0 @@ -66t0 -66t0 99t7 A7q1 -66t0 99t7 A7q1 B7l4 7Al1 -66t0 99t7 A7q1 58k2 BAk0 -66t0 99t7 A7q1 58o6 BAk0 -66t0 99t7 A7q1 68p2 BAo5 -66t0 99t7 A7q1 C8l0 7Al1 -66t0 99t7 A7q1 58l2 BAo5 -66t0 99t7 A7q1 68n2 B9o0 -66t0 99t7 A7q1 58o3 BAk0 -66t0 99t7 A7q1 68o2 38n1 -66t0 99t7 A7q1 6Ap2 BAo5 -66t0 99t7 A7q1 68s1 49o4 -66t0 99t7 A7q1 58l7 38l4 -66t0 99t7 A7q1 58q2 49j0 -66t0 99t7 A7q1 68l4 B9o0 -66t0 99t7 A7q1 69r1 B9o0 -66t0 99t7 A7q1 69p4 49k0 -66t0 99t7 A7q1 C8k0 7Al1 -66t0 99t7 A7q1 69r3 49k0 -66t0 99t7 A7q1 C8m0 7Ak1 -66t0 99t7 A7q1 68k3 38n1 -66t0 99t7 A7q1 68r2 49k1 -66t0 99t7 A7q1 6As0 49k4 -66t0 99t7 A7q1 6Ar0 49s2 -66t0 99t7 A7q1 69s3 49k0 -66t0 99t7 A7q1 5Ao6 BAk0 -66t0 99t7 A7q1 B8o5 7Al1 -66t0 99t7 A7q1 B7o0 7Al1 -66t0 99t7 A7q1 C9o4 7Ak1 -66t0 99t7 A7q1 68f2 BAo5 -66t0 99t7 A7q1 C8r1 7Ak1 -66t0 9At5 98r0 -66t0 9At5 98r0 68r3 35s2 -66t0 9At5 98r0 68s0 48k5 -66t0 9At5 98r0 78u0 49k0 -66t0 9At5 98r0 68k2 47l5 -66t0 9At5 98r0 68p3 48o1 -66t0 9At5 98r0 59k7 38q2 -66t0 9At5 98r0 59q0 49o4 -66t0 9At5 98r0 B8s3 BAl7 -66t0 9At5 98r0 59j2 CAm0 -66t0 9At5 98r0 B8p4 BAl7 -66t0 9At5 98r0 B7l5 A5l3 -66t0 9At5 98r0 B9l1 B5p0 -66t0 9At5 98r0 78m0 49l1 -66t0 9At5 98r0 59o3 38l4 -66t0 9At5 98r0 59l7 49l0 -66t0 9At5 98r0 6Al3 49s1 -66t0 9At5 98r0 B8m1 C6o7 -66t0 9At5 98r0 B7q2 B5p2 -66t0 9At5 98r0 B7o0 B5p2 -66t0 9At5 98r0 B7k4 B5k7 -66t0 9At5 98r0 B7k5 A5j2 -66t0 9At5 98r0 B8k1 B5p2 -66t0 9At5 98r0 78o7 49l0 -66t0 9At5 98r0 59l2 38s2 -66t0 9At5 98r0 B7l4 B5l7 -66t0 9At5 98r0 C8l0 B5l7 -66t0 9At5 98r0 C9o4 B6o6 -66t0 9At5 98r0 CAk0 7Aj0 -66t0 9At5 98r0 B8n1 C6o7 -66t0 9At5 98r0 C8p0 C6p2 -66t0 99t4 A7k6 -66t0 99t4 A7k6 58l2 35r1 -66t0 99t4 A7k6 58k2 35r1 -66t0 99t4 A7k6 68p2 BAr2 -66t0 99t4 A7k6 68n2 BAr2 -66t0 99t4 A7k6 68k3 38n1 -66t0 99t4 A7k6 68l4 BAr2 -66t0 99t4 A7k6 58o6 BAr2 -66t0 99t4 A7k6 68s1 49o4 -66t0 99t4 A7k6 5Al7 BAr2 -66t0 99t4 A7k6 5Ak7 BAr2 -66t0 99t4 A7k6 58k7 38r1 -66t0 99t4 A7k6 68r2 49o4 -66t0 99t4 A7k6 6Bl3 BAr2 -66t0 9Au0 78q2 -66t0 9Au0 78q2 6Bs0 49s1 -66t0 9Au0 78q2 5Bo6 B6p0 -66t0 9Au0 78q2 6Bt0 49s1 -66t0 9Au0 78q2 5Bq0 49l0 -66t0 9Au0 78q2 97s0 6Co6 -66t0 9Au0 78q2 6Bp2 49s1 -66t0 9Au0 78q2 6Ap0 49l4 -66t0 9Au0 78q2 97r0 6Cl2 -66t0 9Au0 78q2 5Bl2 B6p0 -66t0 9Au0 78q2 6At7 49l4 -66t0 9Au0 78q2 6Bo7 B6s2 -66t0 9Au0 78q2 A6q3 6Co6 -66t0 9Au0 78q2 6Ar3 49k4 -66t0 9Au0 78q2 6As3 48o1 -66t0 9Au0 78q2 B7l0 6Cl2 -66t0 9Au0 78q2 6Bm2 49l4 -66t0 9Au0 78q2 A6k4 94l7 -66t0 9Au0 78q2 A6l5 94r1 -66t0 9Au0 78q2 A6o0 94l7 -66t0 9Au0 78q2 A6l4 6Cl2 -66t0 9Au0 78q2 7Br3 5Ao4 -66t0 9Au0 78q2 B8r3 96l2 -66t0 9Au0 78q2 7Cm2 B8k5 -66t0 9Au0 78q2 6Cq0 5Al0 -66t0 9Au0 78q2 B8m5 95u0 -66t0 9Au0 78q2 B8p4 7Ck2 -66t0 9Au0 78q2 B8s3 7Ck2 -66t0 9Au0 78q2 6Ck2 BAp4 -66t0 9Au0 78q2 6Bt3 49l4 -66t0 9Au0 78q2 6Br0 49l4 -66t0 A9t1 97k7 -66t0 A9t1 97k7 7Bl3 D6u0 -66t0 A9t1 97k7 B6r0 94s2 -66t0 A9t1 97k7 6Al7 49s1 -66t0 A9t1 97k7 6Ao3 48o1 -66t0 A9t1 97k7 C5q3 94s2 -66t0 A9t1 97k7 6Aj2 49r1 -66t0 A9t1 97k7 79r3 49o4 -66t0 A9t1 97k7 6Aq0 48u0 -66t0 A9t1 97k7 7Br2 D6l5 -66t0 A9t1 97k7 8Cq1 D6l5 -66t0 A9t1 97k7 6Ak7 49j0 -66t0 A9t1 97k7 7Ao2 49l4 -66t0 A9t1 97k7 B6s0 94l7 -66t0 A9t1 97k7 7Br1 59u0 -66t0 A9t1 97k7 79s3 49o4 -66t0 A9t1 97k7 7Bs1 59o3 -66t0 A9t1 97k7 7Bs2 6Ar1 -66t0 A9t1 97k7 7Bk3 D6u0 -66t0 A9t1 97k7 6Al2 49p4 -66t0 A9t1 97k7 B6k6 A5o7 -66t0 A9t1 97k7 B6p3 6As2 -66t0 A9t1 97k7 7Au0 5Ao4 -66t0 A9t1 97k7 7Bp3 6As1 -66t0 A9t1 97k7 6Aq2 5Al0 -66t0 A9t1 97k7 79l6 49o4 -66t0 A9t1 97k7 7Ap2 49r2 -66t0 A9t1 97k7 7Am1 5Ao4 -66t0 A9t1 97k7 7Ao0 5Ao4 -66t0 A9t1 97k7 C5o1 8Ar3 -66t0 A9t1 97k7 C6l6 A5o7 -66t0 A9t2 97o3 -66t0 A9t2 97o3 78u0 49j0 -66t0 A9t2 97o3 B6r0 94s2 -66t0 A9t2 97o3 C5q3 94s2 -66t0 A9t2 97o3 C6s3 95m3 -66t0 A9t2 97o3 C5l5 7Aj0 -66t0 A9t2 97o3 6Al7 49k4 -66t0 A9t2 97o3 7Bl3 49k4 -66t0 A9t2 97o3 6Ao3 49s2 -66t0 A9t2 97o3 C5o1 C9k4 -66t0 A9t2 97o3 68k2 47l5 -66t0 A9t2 97o3 C6o4 7Aj0 -66t0 A9t2 97o3 B6p3 A5l3 -66t0 A9t2 97o3 B6l1 B9l4 -66t0 A9t2 97o3 C6r3 94r1 -66t0 A9t2 97o3 C6m5 A5l3 -66t0 A9t2 97o3 C6u0 A5l3 -66t0 A9t2 97o3 C6p4 A5l3 -66t0 A9t2 97o3 B6s0 94l7 -66t0 A9t2 97o3 C5k5 A5q1 -66t0 A9t2 97o3 6Aj2 49r1 -66t0 A9t2 97o3 7Bk3 49l4 -66t0 A9t2 97o3 C7r0 A5l3 -66t0 A9t2 97o3 7Br1 5Al0 -66t0 A9t2 97o3 6Aq0 48u0 -66t0 A9t2 97o3 7Bs1 49r2 -66t0 A9t2 97o3 8Bu0 D6l5 -66t0 A9t2 97o3 78o7 49l0 -66t0 A9t2 97o3 C7l1 9Ar3 -66t0 A9t2 97o3 79r3 49k0 -66t0 A9t2 97o3 C6l6 A5l3 -66t0 9At4 79k4 -66t0 9At4 79k4 7Ck2 A8s3 -66t0 9At4 79k4 A6k5 94r1 -66t0 9At4 79k4 97r0 9Co6 -66t0 9At4 79k4 A6q3 ACj2 -66t0 9At4 79k4 97s0 9Co6 -66t0 9At4 79k4 A7p4 A5l3 -66t0 9At4 79k4 B7q3 95o6 -66t0 9At4 79k4 A6k4 9Co6 -66t0 9At4 79k4 A6o0 9Co6 -66t0 9At4 79k4 A7o5 9Co6 -66t0 9At4 79k4 A7k1 9Co6 -66t0 9At4 79k4 A7s3 95o6 -66t0 9At4 79k4 A7r3 A5o7 -66t0 9At4 79k4 A8r0 96l2 -66t0 9At4 79k4 A8l2 9Co6 -66t0 9At4 79k4 A7m6 9Co6 -66t0 9At4 79k4 97l1 94n6 -66t0 9At4 79k4 A6l4 9Co6 -66t0 9At4 79k4 A8l1 A5o7 -66t0 9At4 79k4 A7n1 ACo2 -66t0 9At4 79k4 A7u0 9Co6 -66t0 9At4 79k4 B7n0 ACo2 -66t0 9At4 79k4 B7l5 A5o7 -66t0 9At4 79k4 B8o4 9Co6 -66t0 9At4 79k4 B7k5 9Co6 -66t0 9At4 79k4 B7r2 9Co6 -66t0 9At4 79k4 C8q1 9Co6 -66t0 9At4 79k4 A7o3 9Co6 -66t0 9At4 79k4 B8u0 9Co6 -66t0 AAs1 89l5 -66t0 AAs1 89l5 97r0 73r2 -66t0 AAs1 89l5 97r3 84o7 -66t0 AAs1 89l5 A6q3 73m7 -66t0 AAs1 89l5 88l2 A5o7 -66t0 AAs1 89l5 B7p3 BCk3 -66t0 AAs1 89l5 97l6 A5o7 -66t0 AAs1 89l5 97k6 49r2 -66t0 AAs1 89l5 C7o4 83q2 -66t0 AAs1 89l5 B7l0 94r1 -66t0 AAs1 89l5 C6l5 83q2 -66t0 AAs1 89l5 7Br3 5Ao4 -66t0 AAs1 89l5 B7r0 96k0 -66t0 AAs1 89l5 A6j0 83q2 -66t0 AAs1 89l5 88q0 84k6 -66t0 AAs1 89l5 C6k5 95p3 -66t0 AAs1 89l5 6Cq0 B8o7 -66t0 AAs1 89l5 C6o1 8Dk2 -66t0 AAs1 89l5 A6l5 94n6 -66t0 AAs1 89l5 A6l4 94k7 -66t0 AAs1 89l5 A6k4 94k7 -66t0 AAs1 89l5 A6o0 94r2 -66t0 AAs1 89l5 B7r1 95u0 -66t0 AAs1 89l5 C6q3 96k0 -66t0 AAs1 89l5 C7o5 8Dk2 -66t0 AAs1 89l5 C6o0 8Dk2 -66t0 AAs1 89l5 B7l1 94k7 -66t0 AAs1 89l5 7Co7 5Bs1 -66t0 AAs1 89l5 8Cr3 6Co4 -66t0 AAs1 89l5 C7t3 A7k0 -66t0 AAs1 89l5 C7u0 BCk3 -66t0 9Bl3 5Aq1 -66t0 9Bl3 5Aq1 88o5 84l6 -66t0 9Bl3 5Aq1 79p2 98s3 -66t0 9Bl3 5Aq1 78p3 A5l6 -66t0 9Bl3 5Aq1 78t7 7Ck2 -66t0 9Bl3 5Aq1 78t4 95o3 -66t0 9Bl3 5Aq1 4Co6 89l2 -66t0 9Bl3 5Aq1 5Co7 89l2 -66t0 9Bl3 5Aq1 5Cu0 98r3 -66t0 9Bl3 5Aq1 69m4 98r0 -66t0 9Bl3 5Aq1 87o0 96r0 -66t0 9Bl3 5Aq1 5Co2 89l2 -66t0 9Bl3 5Aq1 4Co3 89l2 -66t0 9Bl3 5Aq1 68q2 98r0 -66t0 9Bl3 5Aq1 5Ct5 98r3 -66t0 9Bl3 5Aq1 5Ct4 98r3 -66t0 9Bl3 5Aq1 79m2 98s3 -66t0 9Bl3 5Aq1 88o2 A7l3 -66t0 9Bl3 5Aq1 78m6 98s3 -66t0 9Bl3 5Aq1 5Cm7 98r3 -66t0 9Bl3 5Aq1 5Cm6 98r3 -66t0 9Bl3 5Aq1 5Dp4 98r3 -66t0 9Bl3 5Aq1 87k4 94p0 -66t0 9Bl3 5Aq1 79n2 98s3 -66t0 9Bl3 5Aq1 78n6 98s3 -66t0 9Bl3 5Aq1 B7o0 A5o7 -66t0 9Bl3 5Aq1 4Cj2 98l6 -66t0 9Bl3 5Aq1 5Cn6 89l2 -66t0 9Bl3 5Aq1 5Dn2 89l2 -66t0 9Bl3 5Aq1 5Ct3 98r3 -66t0 9Bl3 5Aq1 5Ds2 98r3 -66t0 9At6 98r0 -66t0 9At6 98r0 5Ak7 49s1 -66t0 9At6 98r0 5Al7 49s2 -66t0 9At6 98r0 68k2 BBs2 -66t0 9At6 98r0 78o1 49k0 -66t0 9At6 98r0 6Ao2 49s1 -66t0 9At6 98r0 5Ao3 49l0 -66t0 9At6 98r0 5Ao6 49l0 -66t0 9At6 98r0 78u0 49k0 -66t0 9At6 98r0 5Ak2 38q2 -66t0 9At6 98r0 6Ao7 49s1 -66t0 9At6 98r0 6Ak3 49s1 -66t0 9At6 98r0 6Bl3 5Aq1 -66t0 9At6 98r0 5Aq2 49l4 -66t0 9At6 98r0 78o7 48o1 -66t0 9At6 98r0 5Al2 38l4 -66t0 9At6 98r0 CAk0 C6p0 -66t0 9At6 98r0 5Aj2 BBs2 -66t0 9At6 98r0 6Br1 5Al0 -66t0 9At6 98r0 6Bs2 5Al0 -66t0 9At6 98r0 5Cq0 49s1 -66t0 9At6 98r0 B7o0 B5p2 -66t0 9At6 98r0 B9l1 B5p0 -66t0 9At6 98r0 69l6 38l4 -66t0 9At6 98r0 B8m1 B6o6 -66t0 9At6 98r0 6Ap2 49k4 -66t0 9At6 98r0 6Am7 49l4 -66t0 9At6 98r0 6Br3 49l4 -66t0 9At6 98r0 5Ck2 49s1 -66t0 9At6 98r0 5Co6 BAq2 -66t0 9At6 98r0 6Bp0 49l4 -66t0 A8l4 96l7 -66t0 A8l4 96l7 B5p3 94s1 -66t0 A8l4 96l7 B5r0 94r1 -66t0 A8l4 96l7 C5t7 C8k4 -66t0 A8l4 96l7 C5u0 C8k4 -66t0 A8l4 96l7 8Br0 5Ao4 -66t0 A8l4 96l7 8Bs0 49p3 -66t0 A8l4 96l7 8Bt4 D6k5 -66t0 A8l4 96l7 B5s0 94r1 -66t0 A8l4 96l7 B5t4 94s1 -66t0 A8l4 96l7 C5s3 89r3 -66t0 A8l4 96l7 C5r3 C8k4 -66t0 A8l4 96l7 8Ap0 5Ao4 -66t0 A8l4 96l7 8Bt0 49p3 -66t0 A8l4 96l7 8Bt5 D6k5 -66t0 A8l4 96l7 8Bu0 D6k5 -66t0 A8l4 96l7 8Bp2 5Ao4 -66t0 A8l4 96l7 8Bt6 D6k5 -66t0 A8l4 96l7 C4q3 94r1 -66t0 A8l4 96l7 C5t0 C8k4 -66t0 A8l4 96l7 C5t1 94s1 -66t0 A8l4 96l7 C5t2 C8k4 -66t0 A8l4 96l7 8Bt3 5Ao4 -66t0 A8l4 96l7 7Bk7 49r2 -66t0 A8l4 96l7 8Bm2 5Ao4 -66t0 A8l4 96l7 7Bq0 5Ao4 -66t0 A8l4 96l7 C5t3 94s1 -66t0 A8l4 96l7 C4o1 C8k4 -66t0 A8l4 96l7 C6r0 94r1 -66t0 A8l4 96l7 C5m5 C8k4 -66t0 A8l4 96l7 8Bm6 D6k5 -66t0 A9u0 87q2 -66t0 A9u0 87q2 A6k6 74o6 -66t0 A9u0 87q2 B5o1 C9k5 -66t0 A9u0 87q2 6Ao3 49l4 -66t0 A9u0 87q2 B6p4 94l7 -66t0 A9u0 87q2 8Bs0 C6l5 -66t0 A9u0 87q2 8Bt0 C6o1 -66t0 A9u0 87q2 8Bm2 C7k5 -66t0 A9u0 87q2 B6s3 94l7 -66t0 A9u0 87q2 A6r0 94k7 -66t0 A9u0 87q2 B6t3 94s2 -66t0 A9u0 87q2 8Br0 69l5 -66t0 A9u0 87q2 8Bp2 C6o1 -66t0 A9u0 87q2 A6s0 94s1 -66t0 A9u0 87q2 6Al2 49o4 -66t0 A9u0 87q2 6Al7 49l4 -66t0 A9u0 87q2 A6p3 94l7 -66t0 A9u0 87q2 B6m5 94l7 -66t0 A9u0 87q2 8Bt3 69l5 -66t0 A9u0 87q2 7Bs2 C6o1 -66t0 A9u0 87q2 7Br1 C6l5 -66t0 A9u0 87q2 7Bt2 C6l5 -66t0 A9u0 87q2 79r3 49l0 -66t0 A9u0 87q2 6Aq0 59o1 -66t0 A9u0 87q2 B5q3 94r1 -66t0 A9u0 87q2 7Bl2 5Ao4 -66t0 A9u0 87q2 A6t4 94l7 -66t0 A9u0 87q2 B7r0 A5o7 -66t0 A9u0 87q2 8Bk6 C6o1 -66t0 A9u0 87q2 7Bk7 C6l5 -66t0 A9u0 87q2 7Bo3 C6o1 -66t0 B9l0 89r3 -66t0 B9l0 89r3 A4k5 83k4 -66t0 B9l0 89r3 A5o4 94l0 -66t0 B9l0 89r3 95p3 84l3 -66t0 B9l0 89r3 8Bs0 49p3 -66t0 B9l0 89r3 95r0 73l7 -66t0 B9l0 89r3 95s3 73k7 -66t0 B9l0 89r3 A5t2 83q2 -66t0 B9l0 89r3 8Bt0 49p3 -66t0 B9l0 89r3 A4q3 73k7 -66t0 B9l0 89r3 87t4 CBq1 -66t0 B9l0 89r3 A5p4 83q2 -66t0 B9l0 89r3 95t7 73l7 -66t0 B9l0 89r3 95t4 84l3 -66t0 B9l0 89r3 87t7 CBq1 -66t0 B9l0 89r3 A6q1 BBs1 -66t0 B9l0 89r3 A4o1 83l4 -66t0 B9l0 89r3 8Bp2 5Al0 -66t0 B9l0 89r3 ACr2 A7l3 -66t0 B9l0 89r3 A5t1 94s1 -66t0 B9l0 89r3 95s0 73l7 -66t0 B9l0 89r3 95r3 73l7 -66t0 B9l0 89r3 A5t3 83q2 -66t0 B9l0 89r3 A5u0 83q2 -66t0 B9l0 89r3 A5o2 84l3 -66t0 B9l0 89r3 95p0 83q2 -66t0 B9l0 89r3 A5s2 94s2 -66t0 B9l0 89r3 B5r0 83q2 -66t0 B9l0 89r3 ACs1 6Bk6 -66t0 B9l0 89r3 A5r2 94s2 -66t0 B9l0 89r3 A4o0 BBs1 -66t0 8Al7 7Al0 -66t0 8Al7 7Al0 5Bp0 39q2 -66t0 8Al7 7Al0 B8s3 94p0 -66t0 8Al7 7Al0 B8t7 6Dk2 -66t0 8Al7 7Al0 C8m0 6Dk2 -66t0 8Al7 7Al0 5Bs3 39q2 -66t0 8Al7 7Al0 B8r3 A5o7 -66t0 8Al7 7Al0 B8u0 6Dk2 -66t0 8Al7 7Al0 B8t2 6Dk2 -66t0 8Al7 7Al0 B8t1 6Dk2 -66t0 8Al7 7Al0 5Br3 39q2 -66t0 8Al7 7Al0 4Cq0 39q2 -66t0 8Al7 7Al0 5Ct0 4Ar1 -66t0 8Al7 7Al0 5Cs0 4Ar1 -66t0 8Al7 7Al0 B8t3 94r2 -66t0 8Al7 7Al0 B8p4 94p2 -66t0 8Al7 7Al0 C8t5 6Dk2 -66t0 8Al7 7Al0 C8s1 6Dk2 -66t0 8Al7 7Al0 5Bt7 49r2 -66t0 8Al7 7Al0 5Bk1 49r1 -66t0 8Al7 7Al0 C9r3 A7j2 -66t0 8Al7 7Al0 5Ct3 4Ar1 -66t0 8Al7 7Al0 4Co6 8Ck7 -66t0 8Al7 7Al0 5Cu0 4As2 -66t0 8Al7 7Al0 5Cr0 4Ar1 -66t0 8Al7 7Al0 5Ct4 4As2 -66t0 8Al7 7Al0 5Cp2 49r2 -66t0 8Al7 7Al0 5Co5 49s1 -66t0 8Al7 7Al0 6Cr3 4Ar1 -66t0 8Al7 7Al0 A8p3 A5o7 -66t0 8Al7 7Al0 B7k4 94r2 -66t0 8Ao3 59p0 -66t0 8Ao3 59p0 78t5 A5l3 -66t0 8Ao3 59p0 78r1 96r0 -66t0 8Ao3 59p0 78s1 96r0 -66t0 8Ao3 59p0 5Ck2 98r3 -66t0 8Ao3 59p0 5Cl2 98s0 -66t0 8Ao3 59p0 6Bl6 95u0 -66t0 8Ao3 59p0 6Ck6 3Dq0 -66t0 8Ao3 59p0 6Cu0 4Cr3 -66t0 8Ao3 59p0 5Ck7 3Dk1 -66t0 8Ao3 59p0 6Ct4 4Cr3 -66t0 8Ao3 59p0 6Ct5 3Do5 -66t0 8Ao3 59p0 5Bk6 8Ck2 -66t0 8Ao3 59p0 B8s3 A5k3 -66t0 8Ao3 59p0 78i2 96r0 -66t0 8Ao3 59p0 B8t7 8Ck2 -66t0 8Ao3 59p0 A8p3 8Ck2 -66t0 8Ao3 59p0 5Cm3 8Ck2 -66t0 8Ao3 59p0 5Cr1 8Ck2 -66t0 8Ao3 59p0 5Cp3 3Do5 -66t0 8Ao3 59p0 5Ct1 8Ck2 -66t0 8Ao3 59p0 6Cm7 98r0 -66t0 8Ao3 59p0 7Cl6 4Cr3 -66t0 8Ao3 59p0 5Ct2 3Do5 -66t0 8Ao3 59p0 6Cm6 4Cr3 -66t0 8Ao3 59p0 6Dp4 4Cr3 -66t0 8Ao3 59p0 4Bk2 A5o7 -66t0 8Ao3 59p0 4Bk7 A5l3 -66t0 8Ao3 59p0 B7l5 A5l3 -66t0 8Ao3 59p0 B7l4 A5l3 -66t0 8Ao3 59p0 B9l1 95u0 -66t0 AAt6 98l2 -66t0 AAt6 98l2 C7q3 8Ao1 -66t0 AAt6 98l2 88l5 5Ao4 -66t0 AAt6 98l2 79l1 5Ao4 -66t0 AAt6 98l2 79k1 CBk0 -66t0 AAt6 98l2 C7o1 B5r2 -66t0 AAt6 98l2 6Al2 CBk0 -66t0 AAt6 98l2 C8m1 B6o6 -66t0 AAt6 98l2 C8p4 B6o6 -66t0 AAt6 98l2 C7l5 B5s1 -66t0 AAt6 98l2 C7o0 8Bo4 -66t0 AAt6 98l2 C8k1 8Bo4 -66t0 AAt6 98l2 C8o5 8Bo4 -66t0 AAt6 98l2 C7k4 8Bo4 -66t0 AAt6 98l2 C7l4 8Bk0 -66t0 AAt6 98l2 C8s3 B6o6 -66t0 AAt6 98l2 C9l1 C6o7 -66t0 AAt6 98l2 D8p2 B6o6 -66t0 AAt6 98l2 C8m4 B5r2 -66t0 AAt6 98l2 C8n1 B5r2 -66t0 AAt6 98l2 D8n0 B5r2 -66t0 AAt6 98l2 79r3 CBk0 -66t0 AAt6 98l2 79s0 CBk0 -66t0 AAt6 98l2 6Aq0 CBk0 -66t0 AAt6 98l2 C7k5 B5k7 -66t0 AAt6 98l2 7Ap2 5Ao4 -66t0 AAt6 98l2 79s3 CBk0 -66t0 AAt6 98l2 79r0 CBk0 -66t0 AAt6 98l2 88q3 CBk0 -66t0 AAt6 98l2 79l6 49o4 -66t0 AAt6 98l2 C7q2 B5r2 -66t0 AAt2 89p4 -66t0 AAt2 89p4 B7r0 A5o7 -66t0 AAt2 89p4 C7o4 9Co6 -66t0 AAt2 89p4 C6l5 9Co6 -66t0 AAt2 89p4 6Bo6 ACn2 -66t0 AAt2 89p4 7Co6 B8r0 -66t0 AAt2 89p4 C6q3 A5l3 -66t0 AAt2 89p4 6Bk2 49q2 -66t0 AAt2 89p4 7Cl2 5Al4 -66t0 AAt2 89p4 7Bo7 49q2 -66t0 AAt2 89p4 B7p3 A5l3 -66t0 AAt2 89p4 7Al6 49q2 -66t0 AAt2 89p4 8Bl6 5Al4 -66t0 AAt2 89p4 6Bl7 5As1 -66t0 AAt2 89p4 B7s0 A5o7 -66t0 AAt2 89p4 C6k5 8Ck2 -66t0 AAt2 89p4 7Bp2 5Ar1 -66t0 AAt2 89p4 C7u0 9Co6 -66t0 AAt2 89p4 B7k6 A5o7 -66t0 AAt2 89p4 7Bl1 5Ak0 -66t0 AAt2 89p4 7Bo5 5Ao4 -66t0 AAt2 89p4 6Bl2 49q2 -66t0 AAt2 89p4 7Bk6 5Al0 -66t0 AAt2 89p4 7Bo2 B8r0 -66t0 AAt2 89p4 6Bk7 ACn2 -66t0 AAt2 89p4 6Bo3 B8r0 -66t0 AAt2 89p4 7Cl3 B8r0 -66t0 AAt2 89p4 7Ar3 5Al0 -66t0 AAt2 89p4 7As3 5Al0 -66t0 AAt2 89p4 7Bs0 5Ak4 -66t0 AAt2 89p4 7Br0 5As2 -66t0 AAt1 98l2 -66t0 AAt1 98l2 C6q3 95o6 -66t0 AAt1 98l2 79o5 95p3 -66t0 AAt1 98l2 C6l5 A4q2 -66t0 AAt1 98l2 B7r0 94r2 -66t0 AAt1 98l2 6Bo3 49r1 -66t0 AAt1 98l2 7Bo7 49s1 -66t0 AAt1 98l2 6Bo6 49j0 -66t0 AAt1 98l2 78m1 59r0 -66t0 AAt1 98l2 6Bl7 D7o1 -66t0 AAt1 98l2 C6k5 A4q2 -66t0 AAt1 98l2 C7s3 B5p2 -66t0 AAt1 98l2 79p2 49q1 -66t0 AAt1 98l2 7Bo2 49r1 -66t0 AAt1 98l2 B7p3 8Bk1 -66t0 AAt1 98l2 7Bk6 49k4 -66t0 AAt1 98l2 6Bj2 CBk0 -66t0 AAt1 98l2 B7s0 A5o7 -66t0 AAt1 98l2 B7l1 A4q2 -66t0 AAt1 98l2 C6o1 8Bk1 -66t0 AAt1 98l2 C7o4 8Bk1 -66t0 AAt1 98l2 6Bl2 49o4 -66t0 AAt1 98l2 6Bk2 49r1 -66t0 AAt1 98l2 C7r3 B5s1 -66t0 AAt1 98l2 C7m5 B5k7 -66t0 AAt1 98l2 C7u0 B5p2 -66t0 AAt1 98l2 7Cl3 D7o1 -66t0 AAt1 98l2 7Ck3 CAs2 -66t0 AAt1 98l2 69o3 49n1 -66t0 AAt1 98l2 7Al6 49o4 -66t0 AAt1 98l2 C7p4 B5r1 -66t0 A9t7 97k7 -66t0 A9t7 97k7 C7k5 8As0 -66t0 A9t7 97k7 79l6 49n1 -66t0 A9t7 97k7 7Ap2 5Al0 -66t0 A9t7 97k7 79r3 C9o1 -66t0 A9t7 97k7 79s3 C9o1 -66t0 A9t7 97k7 6Aq0 C9o1 -66t0 A9t7 97k7 6Ak7 C9o1 -66t0 A9t7 97k7 6Ao3 49l4 -66t0 A9t7 97k7 7Ao2 49l4 -66t0 A9t7 97k7 7Ak6 49l4 -66t0 A9t7 97k7 7As0 59o1 -66t0 A9t7 97k7 7Ar0 59o1 -66t0 A9t7 97k7 8Ar3 C9o1 -66t0 A9t7 97k7 7Bq0 5Ao4 -66t0 A9t7 97k7 6Al2 49s2 -66t0 A9t7 97k7 C7o0 8As0 -66t0 A9t7 97k7 C8o5 8As0 -66t0 A9t7 97k7 C7k4 8As0 -66t0 A9t7 97k7 7An6 5Al0 -66t0 A9t7 97k7 7Au0 59o1 -66t0 A9t7 97k7 8Al6 5Ao4 -66t0 A9t7 97k7 7Bn2 CAo5 -66t0 A9t7 97k7 79k1 69l5 -66t0 A9t7 97k7 7Bl2 5Ao4 -66t0 A9t7 97k7 7Bo6 C9o1 -66t0 A9t7 97k7 7Bk2 CAj0 -66t0 A9t7 97k7 8Al5 C9o1 -66t0 A9t7 97k7 8Bm2 C9o1 -66t0 A9t7 97k7 7Am1 59o1 -66t0 A9t7 97k7 8Bp2 C9o1 -66t0 AAt5 98p2 -66t0 AAt5 98p2 C7o1 8Br3 -66t0 AAt5 98p2 7Co7 C9o1 -66t0 AAt5 98p2 B6k5 94q2 -66t0 AAt5 98p2 C7l5 8Br3 -66t0 AAt5 98p2 6Cl2 C8k5 -66t0 AAt5 98p2 7Bp0 C7o1 -66t0 AAt5 98p2 6Cq0 5Al0 -66t0 AAt5 98p2 7Bk1 5Ao4 -66t0 AAt5 98p2 A7l1 94l7 -66t0 AAt5 98p2 B8l1 A5l7 -66t0 AAt5 98p2 B6o1 C9o1 -66t0 AAt5 98p2 B7o5 94r1 -66t0 AAt5 98p2 B7o4 C9o1 -66t0 AAt5 98p2 B6o0 94r1 -66t0 AAt5 98p2 B6l4 A5s2 -66t0 AAt5 98p2 6Co6 C8k5 -66t0 AAt5 98p2 C7l0 8Br3 -66t0 AAt5 98p2 7Bs3 5Ao4 -66t0 AAt5 98p2 B7p4 A5r1 -66t0 AAt5 98p2 7Cl1 59u0 -66t0 AAt5 98p2 7Co5 59u0 -66t0 AAt5 98p2 7Br3 5Ao4 -66t0 AAt5 98p2 B7k1 A5l3 -66t0 AAt5 98p2 B7s3 A5o7 -66t0 AAt5 98p2 B6k4 CAn0 -66t0 AAt5 98p2 A7r0 A5l3 -66t0 AAt5 98p2 A7s0 A5l3 -66t0 AAt5 98p2 7Bl6 C8k5 -66t0 AAt5 98p2 B7r3 A5l3 -66t0 AAt5 98p2 B7m4 A5s2 -66t0 A8o0 95r3 -66t0 A8o0 95r3 C5l5 A3o3 -66t0 A8o0 95r3 B5t0 B3o2 -66t0 A8o0 95r3 B5t3 B3j2 -66t0 A8o0 95r3 C5q3 5Al0 -66t0 A8o0 95r3 8Bs0 5Ao4 -66t0 A8o0 95r3 B5s3 B3o7 -66t0 A8o0 95r3 B5r3 B3l6 -66t0 A8o0 95r3 8Ap0 C6k5 -66t0 A8o0 95r3 8Bt0 5Ao4 -66t0 A8o0 95r3 B5p4 B3j2 -66t0 A8o0 95r3 B6r0 A4l2 -66t0 A8o0 95r3 B5t7 C8p4 -66t0 A8o0 95r3 B5u0 C8k5 -66t0 A8o0 95r3 B5m1 C8p4 -66t0 A8o0 95r3 B5t2 C8k5 -66t0 A8o0 95r3 C5p2 A3o3 -66t0 A8o0 95r3 C6u0 C4o7 -66t0 A8o0 95r3 C6t2 89s0 -66t0 A8o0 95r3 C6p4 C4o7 -66t0 A8o0 95r3 B6l1 B3n6 -66t0 A8o0 95r3 C5k5 B3k7 -66t0 A8o0 95r3 B5m4 B3j2 -66t0 A8o0 95r3 B5n1 B3k7 -66t0 A8o0 95r3 C6t3 C4o7 -66t0 A8o0 95r3 C6m4 C4o7 -66t0 A8o0 95r3 C6n1 C4o7 -66t0 A8o0 95r3 D6n0 C4s1 -66t0 A8o0 95r3 7Bl2 5Al0 -66t0 A8o0 95r3 8Bt4 C6k5 -66t0 A8o0 95r3 8Bp2 49s1 -66t0 AAt7 98l2 -66t0 AAt7 98l2 79o5 CAo1 -66t0 AAt7 98l2 C8j0 B5k7 -66t0 AAt7 98l2 C8k4 B5r2 -66t0 AAt7 98l2 78m1 59s3 -66t0 AAt7 98l2 79p2 CBk0 -66t0 AAt7 98l2 C9k1 B6o6 -66t0 AAt7 98l2 C9o5 B6o6 -66t0 AAt7 98l2 69o3 49n1 -66t0 AAt7 98l2 7Al6 CBk0 -66t0 AAt7 98l2 C8k5 B6o6 -66t0 AAt7 98l2 78m6 49o4 -66t0 AAt7 98l2 78p0 5Ao4 -66t0 AAt7 98l2 69k7 49k4 -66t0 AAt7 98l2 78l6 49o4 -66t0 AAt7 98l2 79o2 49n1 -66t0 AAt7 98l2 C8e0 C6o7 -66t0 AAt7 98l2 6Bl2 CBk0 -66t0 AAt7 98l2 6Bk2 CBk0 -66t0 AAt7 98l2 7Ar1 5Ao4 -66t0 AAt7 98l2 69q2 5Ak0 -66t0 AAt4 89l5 -66t0 AAt4 89l5 97p4 BCk3 -66t0 AAt4 89l5 96l5 84o7 -66t0 AAt4 89l5 87l1 84o7 -66t0 AAt4 89l5 8Ck2 6Co4 -66t0 AAt4 89l5 87m1 BCk3 -66t0 AAt4 89l5 8Co3 B8k6 -66t0 AAt4 89l5 97o2 A5k6 -66t0 AAt4 89l5 8Cj2 B8k6 -66t0 AAt4 89l5 87k1 84j2 -66t0 AAt4 89l5 96o0 94s1 -66t0 AAt4 89l5 96o1 84j2 -66t0 AAt4 89l5 87m6 95p3 -66t0 AAt4 89l5 9Co2 B8k6 -66t0 AAt4 89l5 A7l1 94r2 -66t0 AAt4 89l5 87n1 BCk3 -66t0 AAt4 89l5 97m5 BCk3 -66t0 AAt4 89l5 97n0 BCk3 -66t0 AAt4 89l5 8Ck7 B8k6 -66t0 AAt4 89l5 96k5 84j2 -66t0 AAt4 89l5 96k4 94k7 -66t0 AAt4 89l5 97o5 94s1 -66t0 AAt4 89l5 B6l5 BCk3 -66t0 AAt4 89l5 B6k5 BCk3 -66t0 AAt4 89l5 A7r1 A5o7 -66t0 AAt4 89l5 87i3 BCk3 -66t0 AAu0 88o0 -66t0 AAu0 88o0 6Bl2 49l4 -66t0 AAu0 88o0 B7o4 8Ck2 -66t0 AAu0 88o0 B6k5 94q2 -66t0 AAu0 88o0 B6o1 8Ck2 -66t0 AAu0 88o0 B6l5 94q2 -66t0 AAu0 88o0 7Bs0 49r2 -66t0 AAu0 88o0 7Ar3 5Ak0 -66t0 AAu0 88o0 8Br3 B6r2 -66t0 AAu0 88o0 7Bt0 49r2 -66t0 AAu0 88o0 7Cq0 B6r2 -66t0 AAu0 88o0 B7t3 8Ck2 -66t0 AAu0 88o0 B7p4 94l4 -66t0 AAu0 88o0 6Bk2 49l4 -66t0 AAu0 88o0 6Bo6 B6r2 -66t0 AAu0 88o0 8Bl6 B8s3 -66t0 AAu0 88o0 7Cl2 B8s3 -66t0 AAu0 88o0 7Bt3 5Ak0 -66t0 AAu0 88o0 7As3 5Ak0 -66t0 AAu0 88o0 7Bp2 5Al0 -66t0 AAu0 88o0 6Bq0 5Aj0 -66t0 AAu0 88o0 7At7 5Ak0 -66t0 AAu0 88o0 B7t2 94l4 -66t0 AAu0 88o0 B7t1 A5r1 -66t0 AAu0 88o0 7Bo5 5Al0 -66t0 AAu0 88o0 7Ck2 B8s3 -66t0 AAu0 88o0 7Bo7 B8s3 -66t0 AAu0 88o0 7Co6 B8s3 -66t0 AAu0 88o0 A7l1 94q2 -66t0 AAu0 88o0 7Al6 49l4 -66t0 AAu0 88o0 7Br0 5Al0 -66t0 A9s2 A7k3 -66t0 A9s2 A7k3 C5q3 94s2 -66t0 A9s2 A7k3 6Bl7 59o1 -66t0 A9s2 A7k3 78t7 49j0 -66t0 A9s2 A7k3 6Bo3 49r1 -66t0 A9s2 A7k3 7Al6 49s2 -66t0 A9s2 A7k3 6Bk7 49r1 -66t0 A9s2 A7k3 7Bo2 49s1 -66t0 A9s2 A7k3 6Bj2 CAl0 -66t0 A9s2 A7k3 78t4 49j0 -66t0 A9s2 A7k3 C6t3 7Al1 -66t0 A9s2 A7k3 6Bl2 49r2 -66t0 A9s2 A7k3 79p2 58l5 -66t0 A9s2 A7k3 7Bo7 49s1 -66t0 A9s2 A7k3 6Bo6 49r1 -66t0 A9s2 A7k3 C5o1 7Al1 -66t0 A9s2 A7k3 6Bk2 49l4 -66t0 A9s2 A7k3 7Bk6 49l4 -66t0 A9s2 A7k3 7Bp2 49r2 -66t0 A9s2 A7k3 7Ck3 B9l4 -66t0 A9s2 A7k3 7Cl3 CAl0 -66t0 A9s2 A7k3 69o3 49n1 -66t0 A9s2 A7k3 79t0 49o4 -66t0 A9s2 A7k3 79t3 48p0 -66t0 A9s2 A7k3 7Bu0 59o1 -66t0 A9s2 A7k3 7Bt5 5Aj0 -66t0 A9s2 A7k3 7Bt0 59o1 -66t0 A9s2 A7k3 7Bt6 5Ao4 -66t0 A9s2 A7k3 7Bm7 49r2 -66t0 A9s2 A7k3 7Cp4 59o1 -66t0 A9s2 A7k3 C6p4 A4s2 -66t0 A9t6 A7k6 -66t0 A9t6 A7k6 6Bl7 5Al0 -66t0 A9t6 A7k6 6Bo3 49l4 -66t0 A9t6 A7k6 7Bo2 49l4 -66t0 A9t6 A7k6 78m1 5Al0 -66t0 A9t6 A7k6 7Bo7 49l4 -66t0 A9t6 A7k6 6Bo6 49j0 -66t0 A9t6 A7k6 6Bj2 BAr2 -66t0 A9t6 A7k6 7Cl3 CAr1 -66t0 A9t6 A7k6 C6q3 A5l3 -66t0 A9t6 A7k6 6Bl2 49p4 -66t0 A9t6 A7k6 6Bk2 49l4 -66t0 A9t6 A7k6 79p2 48u0 -66t0 A9t6 A7k6 7Bk6 5Al0 -66t0 A9t6 A7k6 79o5 BAr2 -66t0 A9t6 A7k6 7Bp2 49p4 -66t0 A9t6 A7k6 7Bs0 59o1 -66t0 A9t6 A7k6 7Bu0 5Ao4 -66t0 A9t6 A7k6 7Ck3 CAr1 -66t0 A9t6 A7k6 7Cp4 5Ao4 -66t0 A9t6 A7k6 7Cn2 69r2 -66t0 A9t6 A7k6 C6o1 7Al1 -66t0 A9t6 A7k6 78p0 5Ao4 -66t0 A9t6 A7k6 C7s3 A5l3 -66t0 A9t6 A7k6 69o3 49s2 -66t0 A9t6 A7k6 78m6 49o4 -66t0 A9t6 A7k6 7Bm7 5Al0 -66t0 A9t6 A7k6 7Bn6 5Al0 -66t0 A9t6 A7k6 7Bm6 5Ao4 -66t0 A9t6 A7k6 8Co7 CAr1 -66t0 A9t6 A7k6 7Cm3 CAr1 -66t0 B9k0 A5l6 -66t0 B9k0 A5l6 97l5 59o1 -66t0 B9k0 A5l6 88l1 5Ak0 -66t0 B9k0 A5l6 7Bo3 C5r0 -66t0 B9k0 A5l6 8Bo2 C5r0 -66t0 B9k0 A5l6 7Bj2 49r1 -66t0 B9k0 A5l6 7Bl7 C5r0 -66t0 B9k0 A5l6 8Bs0 5Ao4 -66t0 B9k0 A5l6 8Bt4 C5r0 -66t0 B9k0 A5l6 9Bl6 C5r0 -66t0 B9k0 A5l6 8Bt0 5Ao4 -66t0 B9k0 A5l6 8Bu0 C5r0 -66t0 B9k0 A5l6 8Bt5 C5r0 -66t0 B9k0 A5l6 8Bt6 C5r0 -66t0 B9k0 A5l6 9Bq3 C5r0 -66t0 B9k0 A5l6 79l2 49o5 -66t0 B9k0 A5l6 8Cl3 C5r0 -66t0 B9k0 A5l6 8Bt3 5Ak0 -66t0 B9k0 A5l6 8As2 5Ak0 -66t0 B9k0 A5l6 8Bm7 C5r0 -66t0 B9k0 A5l6 8Bn6 5Ao4 -66t0 B9k0 A5l6 8Bm6 C5r0 -66t0 B9k0 A5l6 8Cp4 C5r0 -66t0 B9k0 A5l6 8Cn2 5Ao4 -66t0 B9k0 A5l6 8Cm3 C5r0 -66t0 B9k0 A5l6 8Cr1 C5r0 -66t0 B9k0 A5l6 8Ct2 C5r0 -66t0 B9k0 A5l6 8Cs2 C5r0 -66t0 B9k0 A5l6 7Bq2 C5r0 -66t0 B9k0 A5l6 9Ct3 C5r0 -66t0 B9k0 A5l6 7Bl2 5Ak0 -66t0 AAs0 98p2 -66t0 AAs0 98p2 B8l1 7Bo7 -66t0 AAs0 98p2 C7q3 7Bo7 -66t0 AAs0 98p2 C7l5 7Bo7 -66t0 AAs0 98p2 C7k5 6Br2 -66t0 AAs0 98p2 C7o1 7Bo7 -66t0 AAs0 98p2 C8m5 7Bo7 -66t0 AAs0 98p2 C8t3 7Bo7 -66t0 AAs0 98p2 C8t0 B6o7 -66t0 AAs0 98p2 C8r3 7Bo7 -66t0 AAs0 98p2 C8p4 7Bo7 -66t0 AAs0 98p2 B8r0 A6o6 -66t0 AAs0 98p2 7Al6 CAk5 -66t0 AAs0 98p2 C8u0 7Bu0 -66t0 AAs0 98p2 C8t2 7Bu0 -66t0 AAs0 98p2 C8f5 7Bo7 -66t0 AAs0 98p2 6Bk2 CAk5 -66t0 AAs0 98p2 C8o4 6Br2 -66t0 AAs0 98p2 6Bq0 5Aj0 -66t0 AAs0 98p2 C7l4 7Bo7 -66t0 AAs0 98p2 B8i3 A6o6 -66t0 AAs0 98p2 C8t7 7Bo7 -66t0 AAs0 98p2 C8m1 7Bo7 -66t0 AAs0 98p2 D8p2 7Bo7 -66t0 AAs0 98p2 C8m4 7Bo7 -66t0 AAs0 98p2 C8n1 7Bo7 -66t0 AAs0 98p2 D8n0 7Bo7 -66t0 AAs0 98p2 7Ar3 5Ao4 -66t0 AAs0 98p2 6Bo6 CAk5 -66t0 AAs0 98p2 7Bt0 CAk5 -66t0 AAs0 98p2 C7o0 6Br2 -66t0 AAs3 98p2 -66t0 AAs3 98p2 6Ak7 49l4 -66t0 AAs3 98p2 B6k5 94q2 -66t0 AAs3 98p2 6Al7 49l4 -66t0 AAs3 98p2 6Aq0 59o1 -66t0 AAs3 98p2 B6o1 8Br3 -66t0 AAs3 98p2 6Al2 49r1 -66t0 AAs3 98p2 6Ao3 49l4 -66t0 AAs3 98p2 B7t3 95o6 -66t0 AAs3 98p2 79r3 49o4 -66t0 AAs3 98p2 7Bl3 49l4 -66t0 AAs3 98p2 B7o4 94q2 -66t0 AAs3 98p2 A7t4 95o6 -66t0 AAs3 98p2 C7l0 8Bs0 -66t0 AAs3 98p2 B7p4 A5r1 -66t0 AAs3 98p2 6Aj2 38l4 -66t0 AAs3 98p2 B7u0 A5r2 -66t0 AAs3 98p2 B7t1 A5r1 -66t0 AAs3 98p2 B7t2 A5s2 -66t0 AAs3 98p2 7Ap2 5Aj0 -66t0 AAs3 98p2 7Bp3 5Aq2 -66t0 AAs3 98p2 7Br1 5Al0 -66t0 AAs3 98p2 7Bt1 59o1 -66t0 AAs3 98p2 7At5 5Aj0 -66t0 AAs3 98p2 7Bt2 59o1 -66t0 AAs3 98p2 8Br3 59u0 -66t0 AAs3 98p2 6Aq2 5Al0 -66t0 AAs3 98p2 8Bn0 5Ao4 -66t0 AAs3 98p2 8Bm5 59u0 -66t0 AAs3 98p2 B7o2 A5k3 -66t0 AAs3 98p2 7Bm4 5Ao4 -66t0 AAr2 98l2 -66t0 AAr2 98l2 7Bl3 49j0 -66t0 AAr2 98l2 79k1 95p3 -66t0 AAr2 98l2 88l5 49r2 -66t0 AAr2 98l2 79l1 5Ao4 -66t0 AAr2 98l2 6Aj2 38k4 -66t0 AAr2 98l2 C6q3 95o6 -66t0 AAr2 98l2 6Co6 D7o1 -66t0 AAr2 98l2 7Bs2 59o0 -66t0 AAr2 98l2 7Bp0 49j0 -66t0 AAr2 98l2 6Cl2 49j0 -66t0 AAr2 98l2 6Ck2 59p0 -66t0 AAr2 98l2 6Al7 49k4 -66t0 AAr2 98l2 B7s0 95o6 -66t0 AAr2 98l2 6Ak7 49k4 -66t0 AAr2 98l2 79q0 59p0 -66t0 AAr2 98l2 6Aq0 49o4 -66t0 AAr2 98l2 7Bl6 49j0 -66t0 AAr2 98l2 7Bs3 59o1 -66t0 AAr2 98l2 6Al2 49n1 -66t0 AAr2 98l2 79s0 48p0 -66t0 AAr2 98l2 7Bt2 49r2 -66t0 AAr2 98l2 7Co7 CAk4 -66t0 AAr2 98l2 6Cj2 CAk4 -66t0 AAr2 98l2 7Ct0 7Ak3 -66t0 AAr2 98l2 6Cq0 49o4 -66t0 AAr2 98l2 C6o1 8Bo4 -66t0 AAr2 98l2 6Ao3 49s2 -66t0 AAr2 98l2 79l6 49s2 -66t0 AAr2 98l2 7Ao2 49s2 -66t0 AAr2 98l2 C7o4 B5r1 -66t0 AAu0 -66t0 AAu0 89l5 87t7 -66t0 AAu0 89p4 B6k5 -66t0 AAu0 89p4 B6k5 94l7 7Cl2 -66t0 AAu0 89p4 B6k5 8Ck2 74j2 -66t0 AAu0 89p4 B6k5 94r1 7Cl2 -66t0 AAu0 89p4 B6k5 94s2 7Co6 -66t0 AAu0 89p4 B6k5 96l1 8Bl6 -66t0 AAu0 89p4 B6k5 83q2 7Cl2 -66t0 AAu0 89p4 B6k5 95m5 B3r0 -66t0 AAu0 89p4 B6k5 94k7 7Cj2 -66t0 AAu0 98l2 78t7 -66t0 AAu0 98p2 6Bk2 -66t0 AAu0 98p2 6Bk2 C8k5 47j0 -66t0 AAu0 98p2 6Bk2 49l4 C7l5 -66t0 AAu0 98p2 6Bk2 49s1 C7l5 -66t0 AAu0 98p2 6Bk2 49r1 C7l5 -66t0 AAu0 98p2 6Bk2 49k4 C7o1 -66t0 AAu0 98p2 6Bk2 38q2 C7l5 -66t0 AAu0 98p2 6Bk2 59m2 3Br3 -66t0 AAu0 98p2 6Bk2 69l6 B8l1 -66t0 AAu0 98p2 6Bk2 49q0 3Br3 -66t0 AAu0 98p2 6Bk2 48u0 C7l5 -66t0 AAu0 98p2 6Bk2 38l7 C7o1 -66t0 AAu0 88o3 6Bk2 -66t0 AAu0 88o3 6Bk2 49k7 C7l5 -66t0 AAu0 88o3 6Bk2 49q2 C7o1 -66t0 AAu0 88o3 6Bk2 C8k5 47j0 -66t0 AAu0 88o3 6Bk2 49s1 C7l5 -66t0 AAu0 88o3 6Bk2 49r1 C7l5 -66t0 AAu0 95o6 97t0 -66t0 AAu0 97o3 78t7 -66t0 AAu0 97o6 78t7 -66t0 AAu0 88o0 B6k5 -66t0 AAu0 88o0 B6k5 8Ck2 74j2 -66t0 AAu0 88o0 B6k5 94q2 7Co6 -66t0 AAu0 88o0 B6k5 94k4 7Cl2 -66t0 AAu0 A5o7 97t0 -66t0 AAu0 A5k3 97t0 -66t0 AAu0 A5l6 C7l0 -66t0 AAu0 98k2 78t7 -66t0 AAu0 7Ao4 7Cn2 -66t0 AAu0 79o1 87t4 -66t0 AAu0 96l2 C7l0 -66t0 AAu0 69l5 7Cl3 -66t0 AAu0 69l5 7Cl3 4Co4 88o7 -66t0 AAu0 69l5 7Cl3 4Ck0 88o7 -66t0 AAu0 69l5 7Cl3 4Ck1 88o7 -66t0 AAu0 A5l3 97t0 -66t0 AAu0 5Al1 7Cl3 -66t0 AAu0 97p3 78t7 -66t0 AAu0 88o6 C7k5 -66t0 AAu0 88o6 C7k5 A5s2 C4r0 -66t0 AAu0 88o6 C7k5 A5l7 79p2 -66t0 AAu0 88o6 C7k5 6Bl0 94r0 -66t0 AAu0 88o6 C7k5 A5r1 6Bo3 -66t0 AAu0 A7o7 C7n0 -66t0 AAu0 88k4 B6k5 -66t0 AAu0 88k7 6Bk2 -66t0 AAu0 A5o2 97t0 -66t0 AAu0 98m2 78t7 -66t0 AAu0 94p0 97p4 -66t0 AAu0 98o7 79p2 -66t0 AAu0 95k2 97t0 -66t0 AAu0 98o2 C7k5 -66t0 AAu0 98o2 C7k5 94r2 6Bj2 -66t0 AAu0 98o2 C7k5 8Cq0 94t7 -66s0 99t7 -66s0 99t7 96r0 C8l0 -66s0 99t7 96r0 C8l0 6Ao5 A4s3 -66s0 99t7 79r3 85q3 -66s0 99t7 95p3 C7o7 -66s0 99t7 95t4 B6k0 -66s0 99t7 96t3 58l2 -66s0 99t7 A5q3 B7l4 -66s0 99t7 A5o2 67l6 -66s0 99t7 6Ao4 7Cl3 -66s0 99t7 95t1 67l6 -66s0 99t7 6Al0 85l4 -66s0 99t7 69t7 6Bk2 -66s0 99t7 69u0 6Bk2 -66s0 99t7 6Ak0 85q3 -66s0 99t7 6Aq1 6Bl7 -66s0 99t7 6Al1 85l4 -66s0 99t7 95t7 B6s2 -66s0 99t7 69t4 6Bl2 -66s0 99t7 59p3 6Bo3 -66s0 99t7 6Aq0 7Bk6 -66s0 99t7 69t6 6Bj2 -66s0 99t7 95t2 67l6 -66s0 99t7 69m5 6Bn2 -66r0 99t7 -66r0 99t7 A5l3 67r3 -66r0 99t7 6Al0 85l5 -66r0 99t7 A5q3 B7l4 -66r0 99t7 96s3 B7o0 -66r0 99t7 95t4 B6k0 -66r0 99t7 96t3 B6p0 -66r0 99t7 95o1 B6p0 -66r0 99t7 95l5 67r3 -66r0 99t7 A5o2 58l7 -66r0 99t7 59p3 6Bo3 -66r0 99t7 69t7 7Bo2 -66r0 99t7 69p0 6Bj2 -66r0 99t7 69t6 6Bj2 -66r0 99t7 69u0 7Bo2 -66r0 99t7 59t1 85k5 -66r0 99t7 95p3 B6r2 -56l2 AAt1 -56l2 AAt1 97t5 78p0 -56l2 AAt1 97u0 78p0 -56l2 AAt1 98p2 B7r0 -56l2 AAt1 87q2 C6q3 -56l2 AAt1 97t1 78s3 -56l2 AAt1 97s1 78s3 -56l2 AAt1 96t6 78s3 -56l2 AAt1 98t0 C6o1 -56l2 AAt1 89k0 97r0 -56l2 AAt1 89o4 97r0 -56l2 AAt1 88o1 97r0 -56l2 AAt1 78t1 7Ar3 -56l2 AAt1 88t7 97s3 -56l2 AAt1 98r3 C6o1 -56l2 AAt1 95t2 97s0 -56l2 AAt1 88o0 97r0 -56l2 AAt1 96s3 C7p4 -56l2 AAt1 88r1 A6l4 -56l2 AAt1 89o5 97r0 -56l2 AAt1 96r2 78s3 -56l2 AAt1 A7q1 B7l1 -56l2 AAt1 96t3 88o4 -56l2 AAt1 96p0 C7p4 -56l2 AAt1 96s2 A6l4 -56l2 AAt1 95t1 97s0 -56l2 AAt1 88u0 97r0 -56l2 AAt1 58t0 97r0 -56l2 AAt1 98t3 C6q3 -56l2 AAt1 95u0 88o4 -56l2 AAt1 94t6 88k0 -56p0 B9t6 -56p0 B9t6 79t2 7Bk7 -56p0 B9t6 79t2 7Bk7 5Co4 97o7 -56p0 B9t6 79t2 7Bk7 5Bo1 97o7 -56p0 B9t6 79s2 87o6 -56p0 B9t6 78r2 98k0 -56p0 B9t6 7Al1 8Cn2 -56p0 B9t6 89s3 7Bl2 -56p0 B9t6 88u0 8Al6 -56p0 B9t6 86o3 88s0 -56p0 B9t6 86t1 88r3 -56p0 B9t6 89s0 7Bl2 -56p0 B9t6 89r0 7Bl2 -56p0 B9t6 89r3 7Bl2 -56p0 B9t6 7Ao4 97o7 -56p0 B9t6 88r1 8Al6 -56p0 B9t6 69l4 97o7 -56p0 B9t6 79m3 87o6 -56p0 B9t6 89k5 87o6 -56p0 B9t6 7Ak0 8Cl3 -56p0 B9t6 88t1 8Al6 -56p0 B9t6 7Al0 7Bl7 -56p0 B9t6 96o2 88s0 -56p0 B9t6 69t1 7Bk7 -56p0 B9t6 79l3 87o6 -56p0 B9t6 79o7 8Bm7 -56p0 B9t6 88o3 7Bj2 -56p0 B9t6 88t2 8Al6 -56p0 B9t6 98k3 B6p3 -56p0 B9t6 98o2 7Bj2 -56p0 B9t6 87s2 79o3 -56p0 B9t6 98k6 7Bk2 -56p0 B9t6 86u0 88r3 -66l2 AAp3 -66l2 AAp3 A7p3 87q3 -66l2 AAp3 A8k2 88m0 -66l2 AAp3 A6p0 C6o0 -66l2 AAp3 A7t7 88m0 -66l2 AAp3 A7t4 88m0 -66l2 AAp3 A6k0 C6j0 -66l2 AAp3 B7k6 88m0 -66l2 AAp3 B7o7 88m0 -66l2 AAp3 B7o2 88m0 -66l2 AAp3 59o4 87q3 -66l2 AAp3 A7t1 C6k5 -66l2 AAp3 A6t6 C6o0 -66l2 AAp3 58t4 87q3 -66l2 AAp3 58s3 7Cr1 -66l2 AAp3 58s3 7Cr1 89t3 A6l5 -66l2 AAp3 58s3 7Cr1 89p4 A6l5 -66l2 AAp3 58t7 78r3 -66l2 AAp3 58r0 6Bk7 -66l2 AAp3 58t3 A6l5 -66l2 AAp3 58t3 A6l5 94k6 6Bk2 -66l2 AAp3 58t3 A6l5 84o6 B3q3 -66l2 AAp3 58t3 A6l5 83r2 A2k5 -66l2 AAp3 58t3 A6l5 94q1 78r0 -66l2 AAp3 58t3 A6l5 84m3 7Bt5 -66l2 AAp3 58t3 A6l5 94k3 B3k5 -66l2 AAp3 58t3 A6l5 84n2 6Bq2 -66l2 AAp3 58t3 A6l5 83p0 B4t0 -66l2 AAp3 58u0 87q3 -66l2 AAp3 A6n0 C6k5 -66l2 AAp3 A8n2 87q3 -66l2 AAp3 A7o6 89l0 -66l2 AAp3 58p0 87q3 -66l2 AAp3 B7q1 C6j0 -66l2 AAp3 B7q1 C6j0 8Ao4 A3o2 -66l2 AAp3 58o1 87q3 -66l2 AAp3 58t6 87q3 -66l2 AAp3 58t5 87q3 -66l2 AAp3 A5o1 C6o0 -66l2 AAp3 B7k3 89l0 -66l2 AAp3 A6r2 89l0 -66l2 AAp3 A7s1 87q3 -56t6 A9t6 -56t6 A9t6 85p3 77o6 -56t6 A9t6 97o7 A6r0 -56t6 A9t6 87o3 69q0 -56t6 A9t6 88q3 77o6 -56t6 A9t6 79r0 7Ar3 -56t6 A9t6 87k7 69q0 -56t6 A9t6 79s3 6Bo3 -56t6 A9t6 88l5 7As3 -56t6 A9t6 87o6 A6s0 -56t6 A9t6 85s0 B5l5 -56t6 A9t6 86r2 B5k5 -56t6 A9t6 88k5 95l4 -56t6 A9t6 97o2 78s0 -56t6 A9t6 87r1 B5q3 -56t6 A9t6 79l1 7Ar3 -56t6 A9t6 97k3 B6s3 -56t6 A9t6 79s0 6Bk2 -56t6 A9t6 87s1 B5q3 -56t6 A9t6 79r3 6Bk2 -56t6 A9t6 78u0 6Bl2 -56t6 A9t6 84r2 B6u0 -56t6 A9t6 88p4 7Ar3 -56t6 A9t6 79p4 6Bl2 -56t6 A9t6 87u0 A6r0 -56t6 A9t6 87n6 A6r0 -56t6 A9t6 84s2 96o2 -56o6 AAp3 -56o6 AAp3 89k0 6Bq0 -56o6 AAp3 A7q1 78t7 -56o6 AAp3 87q2 B7r0 -56o6 AAp3 96p0 78t7 -56o6 AAp3 97t1 78t4 -56o6 AAp3 97u0 78t7 -56o6 AAp3 97t5 78t7 -56o6 AAp3 98t0 B7r0 -56o6 AAp3 96s2 88k2 -56o6 AAp3 96t6 78r0 -56o6 AAp3 96s3 88q0 -56o6 AAp3 95t2 C6o0 -56o6 AAp3 A5q3 88o4 -56o6 AAp3 96r2 78t7 -56o6 AAp3 88k4 A6q3 -56o6 AAp3 A7k3 78t7 -56o6 AAp3 A7k6 78s3 -56o6 AAp3 96r0 88q0 -56o6 AAp3 97s1 78t7 -56o6 AAp3 98p4 B7r0 -56o6 AAp3 98t3 B7r0 -56o6 AAp3 78t1 7Ar3 -56o6 AAp3 95t1 88o4 -56o6 AAp3 94r2 88o4 -56o6 AAp3 94t6 88k0 -56o6 AAp3 A7l6 78t7 -56o6 AAp3 98l2 78t7 -56o6 AAp3 A7j2 78t7 -56o6 AAp3 98s3 B7r0 -56o6 AAp3 87l7 B7r0 -65s0 99r3 -65s0 99r3 A7k3 C8k0 -65s0 99r3 68t7 86l1 -65s0 99r3 A7l3 C8l0 -65s0 99r3 A7l3 C8l0 68p0 6Bk2 -65s0 99r3 A7l3 C8l0 68t7 6As0 -65s0 99r3 A7l3 C8l0 68t4 6As0 -65s0 99r3 96l7 57l2 -65s0 99r3 69o4 7Bo2 -65s0 99r3 68p0 6Ao2 -65s0 99r3 68t4 86l1 -65s0 99r3 97o6 57l2 -65s0 99r3 A7o7 57l2 -65s0 99r3 96r2 B7s1 -65s0 99r3 96t6 B7s1 -65s0 99r3 69k0 6Bk3 -65s0 99r3 A7l6 C8s2 -65s0 99r3 68o1 7Bo2 -65s0 99r3 97t4 B7o0 -65s0 99r3 97t7 B8n1 -65s0 99r3 A7q1 B7k0 -65s0 99r3 97u0 B7o0 -65s0 99r3 98l2 C8k0 -65s0 99r3 98r0 57l2 -65s0 99r3 96p0 B7s2 -65s0 99r3 97t1 B7o0 -65s0 99r3 97t2 57l2 -65s0 99r3 58r2 86l1 -65s0 99r3 58p3 6Am6 -65s0 99r3 58t2 86l1 -65s0 99r3 57n6 6Am6 -65s0 99r3 97o4 57l2 -65s0 99r3 A7k6 C8k0 -65s0 99r3 A7o2 C8k0 -56t4 99r0 -56t4 99r0 7Ak0 8Cq1 -56t4 99r0 7Ak0 8Cq1 A7l6 CAt6 -56t4 99r0 7Ak0 8Cq1 97p3 CAt6 -56t4 99r0 7Ak0 8Cq1 97s0 CAt6 -56t4 99r0 7Al1 8Cs1 -56t4 99r0 7Ao4 8Cs1 -56t4 99r0 7Ao4 8Cs1 A7l6 76p4 -56t4 99r0 7Ao4 8Cs1 97p3 4Bq0 -56t4 99r0 7Ao4 8Cs1 95l3 B6l0 -56t4 99r0 7Ao4 8Cs1 84l7 B6l0 -56t4 99r0 7Ao4 8Cs1 97s0 75o1 -56t4 99r0 7Ao4 8Cs1 95j2 C7l0 -56t4 99r0 7Ao4 8Cs1 84s2 86k7 -56t4 99r0 7Ao4 8Cs1 A7k6 76p4 -56t4 99r0 7Ao4 8Cs1 86r0 4Bq0 -56t4 99r0 7Ao4 8Cs1 95l6 B6n0 -56t4 99r0 7Ao4 8Cs1 86s3 96l1 -56t4 99r0 7Ao4 8Cs1 5Cp0 76p4 -56t4 99r0 7Ao4 8Cs1 5Cs3 76t3 -56t4 99r0 7Ao4 8Cs1 5Cr0 75l5 -56t4 99r0 7Ao4 8Cs1 74u0 4Bq0 -56t4 99r0 7Al0 8Cl3 -56t4 99r0 7Al0 8Cl3 95o7 B6s2 -56t4 99r0 69l4 8Cl3 -56t4 99r0 69l4 8Cl3 95o7 B6s2 -56t4 99r0 69l4 8Cl3 86r0 A6t3 -56t4 99r0 7Aq0 75l5 -56t4 99r0 7Aq1 7Bk3 -56t4 99r0 5Ao5 75l5 -56t4 99r0 5Ao5 75l5 9Bj2 44s2 -56t4 99r0 89r3 75l5 -56t4 99r0 89r3 75l5 53s1 ACt1 -56t4 99r0 89r3 75l5 53k7 93p2 -56t4 99r0 89r3 75l5 CBq1 44s2 -56t4 99r0 89r3 75l5 42q2 ACt1 -56t4 99r0 89r3 75l5 BBl0 44s2 -56t4 99r0 89r3 75l5 BBo4 44s2 -56t4 99r0 89r3 75l5 43o3 83t0 -56t4 99r0 89r3 75l5 53p2 ACk3 -56t4 99r0 79o1 8Ck3 -56t4 99r0 79o1 8Ck3 5Bk5 76p4 -56t4 99r0 79o1 8Ck3 5Ck0 76p4 -56t4 99r0 79o1 8Ck3 5Ck1 76p4 -56t4 99r0 79o1 8Ck3 A7l6 4At4 -56t4 99r0 79u0 7Bk7 -56t4 99r0 79u0 7Bk7 5Bo1 75l5 -56t4 99r0 79u0 7Bk7 5Co4 75l5 -56t4 99r0 79u0 7Bk7 5Bk5 75l5 -56t4 99r0 79u0 7Bk7 5Ck1 75l5 -56t4 99r0 79u0 7Bk7 5Ck0 75l5 -56t4 99r0 79u0 7Bk7 5Cl0 76t3 -56t4 99r0 79u0 7Bk7 A7l6 49p0 -56t4 99r0 79u0 7Bk7 A7k6 76p4 -56t4 99r0 69r2 7Bk3 -56t4 99r0 69r2 7Bk3 A7l6 CAt6 -56t4 99r0 69r2 7Bk3 A7k6 76p4 -56t4 99r0 69r2 7Bk3 97p3 76p4 -56t4 99r0 69r2 7Bk3 95o7 B6p0 -56t4 99r0 95l6 B6k4 -56t4 99r0 85p3 A6k1 -56t4 99r0 5Al1 79l5 -56t4 99r0 59o0 75l5 -56t4 99r0 79o7 7Bk7 -56t4 99r0 95k3 69p2 -56t4 99r0 69p3 7Bt1 -56t4 99r0 79p0 7Bj2 -56t4 99r0 95l3 69p2 -56t4 99r0 69s1 7Bk3 -65t0 A9u0 -65t0 A9u0 97l2 C6l5 -65t0 A9u0 96o3 C6k5 -65t0 A9u0 88p4 7Bk2 -65t0 A9u0 59l0 77p3 -65t0 A9u0 88l5 7Bk7 -65t0 A9u0 59o4 87o7 -65t0 A9u0 79o4 7Bn2 -65t0 A9u0 58o1 7Bl3 -65t0 A9u0 87k7 6Al7 -65t0 A9u0 87o3 6Al7 -65t0 A9u0 97o2 6Al7 -65t0 A9u0 78p0 7Ao2 -65t0 A9u0 96u0 B5l5 -65t0 A9u0 87o6 6Al7 -65t0 A9u0 87k4 7Bk2 -65t0 A9u0 78o1 7Br2 -65t0 A9u0 97k2 C6k5 -65t0 A9u0 A6o7 C6s2 -65t0 A9u0 97p2 7Ao2 -65t0 A9u0 86q2 B5k5 -65t0 A9u0 59l1 7Br1 -65t0 A9u0 59o5 7Bl3 -65t0 A9u0 58o0 7Bl3 -65t0 A9u0 97m2 77t7 -65t0 A9u0 97o7 78p2 -65t0 A9u0 A4k6 87o4 -65t0 A9u0 78o0 7Bk2 -65t0 A9u0 96o6 C6s2 -65t0 A9u0 87r1 7As0 -65t0 A9u0 68l5 7Bt1 -66p2 9Au0 -66p2 9Au0 6Ao4 6Ck3 -66p2 9Au0 79l5 6Cl2 -66p2 9Au0 97s1 B7k0 -66p2 9Au0 A7l3 B7r2 -66p2 9Au0 4Ak1 86o0 -66p2 9Au0 59l5 6Cl3 -66p2 9Au0 69o1 6Cs1 -66p2 9Au0 78k7 97r0 -66p2 9Au0 78o3 97r0 -66p2 9Au0 4Al1 6Cl3 -66p2 9Au0 69o0 6Cn2 -66p2 9Au0 A7l6 C8n0 -66p2 9Au0 49k5 86o0 -66p2 9Au0 4Ao4 86q2 -66p2 9Au0 4Ak0 86o0 -66p2 9Au0 49o1 86q2 -66p2 9Au0 49o0 69t3 -66p2 9Au0 79t3 6Co6 -66p2 9Au0 79t0 97r0 -66p2 9Au0 A7q3 68l6 -66p2 9Au0 6Ak0 6Ck3 -66p2 9Au0 98r0 68l6 -66p2 9Au0 98n2 B8k1 -66p2 9Au0 97n6 B8k1 -66p2 9Au0 97t1 B7o0 -66p2 9Au0 97t5 B7s2 -66p2 9Au0 96t6 B7r1 -66p2 9Au0 88t6 97r0 -66p2 9Au0 88t5 97r0 -66p2 9Au0 69t4 86o0 -66k2 AAr0 -66k2 AAr0 B7q1 77k6 -66k2 AAr0 A6p0 77k6 -66k2 AAr0 98t5 7At6 -66k2 AAr0 A7t5 77k6 -66k2 AAr0 A5p3 C7s1 -66k2 AAr0 58l5 77l6 -66k2 AAr0 98o6 7At6 -66k2 AAr0 A6r2 77k6 -66k2 AAr0 B7o7 77k6 -66k2 AAr0 A7t4 77k6 -66k2 AAr0 A7m7 C7j0 -66k2 AAr0 A7o6 77k6 -66k2 AAr0 A7t7 77k6 -66k2 AAr0 A6t6 77k6 -66k2 AAr0 49l1 B7o5 -66k2 AAr0 A6s2 77k6 -66k2 AAr0 A6s3 C7s2 -66k2 AAr0 A6r0 C7t6 -66k2 AAr0 A6t3 C7k0 -66k2 AAr0 48u0 77l6 -66k2 AAr0 48t3 68l2 -66k2 AAr0 A8s0 77k6 -66k2 AAr0 A8n2 C7j0 -66k2 AAr0 B7q3 77k6 -66k2 AAr0 A8r0 77k6 -66k2 AAr0 A7t1 77k6 -66k2 AAr0 A7n6 C7j0 -66k2 AAr0 A7p3 77k6 -66k2 AAr0 A8m2 77k6 -66k2 AAr0 A5t1 C7s1 -65t4 9Bt1 -65t4 9Bt1 97r1 78o1 -65t4 9Bt1 68u0 88r0 -65t4 9Bt1 97s1 79o4 -65t4 9Bt1 88r1 5Aq0 -65t4 9Bt1 87r2 89k3 -65t4 9Bt1 69o5 88r0 -65t4 9Bt1 97m0 78o1 -65t4 9Bt1 78l4 B8p4 -65t4 9Bt1 78l4 B8p4 6Co7 85k1 -65t4 9Bt1 78l4 B8p4 A6o6 6Br3 -65t4 9Bt1 78l4 B8p4 6Cu0 85s3 -65t4 9Bt1 98r3 79o4 -65t4 9Bt1 88u0 69r3 -65t4 9Bt1 98r0 79o4 -65t4 9Bt1 68o0 88s3 -65t4 9Bt1 78s1 5Aq0 -65t4 9Bt1 97u0 B7k5 -65t4 9Bt1 78r2 97o0 -65t4 9Bt1 97l0 78o1 -65t4 9Bt1 A7l6 C8n0 -65t4 9Bt1 A7k3 79o4 -65t4 9Bt1 58l4 88r3 -65t4 9Bt1 97o4 78o1 -65t4 9Bt1 98p2 78o1 -65t4 9Bt1 98s3 79o4 -65t4 9Bt1 A7o7 79k0 -65t4 9Bt1 88o0 B7l5 -65t4 9Bt1 96l7 79o4 -65t4 9Bt1 89o5 B7l5 -65t4 9Bt1 58p4 6As1 -65t4 9Bt1 94o6 6Ao7 -65t4 9Bt1 A4o7 6Ao7 -65t4 9Bt1 88o1 5Ao6 -65u0 9At1 -65u0 9At1 58p0 78m5 -65u0 9At1 79o5 87r0 -65u0 9At1 78o0 87r0 -65u0 9At1 58t7 78m5 -65u0 9At1 78k4 6Ar3 -65u0 9At1 77q2 B6q3 -65u0 9At1 68t0 6Ar3 -65u0 9At1 68t1 6Ar3 -65u0 9At1 88k2 59l7 -65u0 9At1 79o4 7Br3 -65u0 9At1 68r3 78l2 -65u0 9At1 88p2 6Ar3 -65u0 9At1 78r1 6Ar3 -65u0 9At1 68r2 5Bk2 -65u0 9At1 88l2 59l7 -65u0 9At1 78o1 6As3 -65u0 9At1 97r3 B6o0 -65u0 9At1 68s0 96l5 -65u0 9At1 97l6 B7r3 -65u0 9At1 97s0 59l7 -65u0 9At1 79k0 6Bs0 -65u0 9At1 97p2 B6l5 -65u0 9At1 88q0 77o1 -65u0 9At1 78s2 6Ar3 -65u0 9At1 58s3 78m5 -65u0 9At1 78t2 6Ar3 -65u0 9At1 78p0 6Ar3 -65u0 9At1 87t5 A7l1 -65u0 9At1 78t7 6Ar3 -65u0 9At1 87t6 A7l1 -56r0 99r0 -56r0 99r0 7Ak0 8Ck3 -56r0 99r0 7Ak0 8Ck3 A7l6 76t3 -56r0 99r0 7Al0 7Bl7 -56r0 99r0 69l4 7Bs2 -56r0 99r0 7Ao4 75l5 -56r0 99r0 69t1 7Bp3 -56r0 99r0 7Aq1 8Ct2 -56r0 99r0 79o1 75l5 -56r0 99r0 79t6 8Bo2 -56r0 99r0 79u0 7Bo3 -56r0 99r0 69s1 7Bs2 -56r0 99r0 69p3 7Bt1 -56r0 99r0 7Al1 75l5 -56r0 99r0 79p0 8Bo2 -56r0 99r0 79t4 7Bq2 -56r0 99r0 79t7 7Bo3 -56r0 99r0 95o7 59o3 -56r0 99r0 95l6 B6t6 -56r0 99r0 95l3 59k7 -56r0 99r0 79o7 75l5 -56r0 99r0 7Aq0 75l5 -56r0 99r0 59t6 7Bk0 -56r0 99r0 95k3 59l2 -56r0 99r0 86l2 B6s2 -56r0 99r0 69k3 7Bt1 -56r0 99r0 59t5 6As1 -56r0 99r0 5Ao5 75l5 -56r0 99r0 85o6 68l6 -56r0 99r0 89l5 8Ck3 -56r0 99r0 7Ak1 8Ck3 -56r0 99r0 85k2 68l6 -75l6 AAt4 -75l6 AAt4 B7q1 88n0 -75l6 AAt4 A7p3 88n0 -75l6 AAt4 A7t7 88n0 -75l6 AAt4 A7t4 89q1 -75l6 AAt4 A6p0 88n0 -75l6 AAt4 A8r0 88n0 -75l6 AAt4 98o6 78n1 -75l6 AAt4 A7t1 88n0 -75l6 AAt4 A6r2 88n0 -75l6 AAt4 A7u0 88n0 -75l6 AAt4 68t4 6Bl7 -75l6 AAt4 A5p3 C7l0 -75l6 AAt4 68t7 88m5 -75l6 AAt4 58r2 87m6 -75l6 AAt4 A8s0 88n0 -75l6 AAt4 A8n2 88n0 -75l6 AAt4 B7o7 88n0 -75l6 AAt4 A7n6 88n0 -75l6 AAt4 A7t5 88n0 -75l6 AAt4 68o1 6Bl7 -75l6 AAt4 69o4 6Bo3 -75l6 AAt4 B7o2 88n0 -75l6 AAt4 A6s2 88n0 -75l6 AAt4 A6s3 C7s2 -75l6 AAt4 68s3 6Bl7 -75l6 AAt4 58t1 96k5 -75l6 AAt4 A7s1 88n0 -75l6 AAt4 B7q3 88n0 -75l6 AAt4 A8m2 88n0 -75l6 AAt4 B7k3 88n0 -56o0 A9t7 -56o0 A9t7 5As1 7Bl3 -56o0 A9t7 6At6 77p0 -56o0 A9t7 84p2 79l6 -56o0 A9t7 6Bk1 8Cs2 -56o0 A9t7 5Ap2 7Bk3 -56o0 A9t7 87k7 B5q3 -56o0 A9t7 89l6 77p0 -56o0 A9t7 85t1 77p0 -56o0 A9t7 6At5 7Bo3 -56o0 A9t7 7Al2 77p0 -56o0 A9t7 85t2 77p0 -56o0 A9t7 85u0 77p0 -56o0 A9t7 84t5 86p3 -56o0 A9t7 5Ar3 8Cq1 -56o0 A9t7 6Am4 7Bl7 -56o0 A9t7 7Ak2 77p0 -56o0 A9t7 6Ap0 77p0 -56o0 A9t7 85t7 B5l4 -56o0 A9t7 85p3 B5q2 -56o0 A9t7 5At1 88l3 -56o0 A9t7 85t4 B5k4 -56o0 A9t7 84p0 96o2 -56o0 A9t7 85m3 96o2 -56o0 A9t7 84r2 86p3 -56o0 A9t7 5Al4 77p0 -56o0 A9t7 84t6 86p3 -56o0 A9t7 84s2 B5o0 -56o0 A9t7 84m7 86m6 -56o0 A9t7 84s1 86p3 -56o0 A9t7 84r1 B5o0 -56k4 99s3 -56k4 99s3 7At0 77l0 -56k4 99s3 89q3 77l0 -56k4 99s3 7At3 77l0 -56k4 99s3 7Ar0 77l0 -56k4 99s3 7Ap2 77l0 -56k4 99s3 79n6 75j0 -56k4 99s3 79t4 77l0 -56k4 99s3 79t7 77l0 -56k4 99s3 7Am2 75j0 -56k4 99s3 6Ao6 77l0 -56k4 99s3 7An2 75j0 -56k4 99s3 7As3 77l0 -56k4 99s3 6Ao0 76o5 -65t2 9Ar0 -65t2 9Ar0 78o0 6Bq0 -65t2 9Ar0 87k7 B7j0 -65t2 9Ar0 88k2 B7l5 -65t2 9Ar0 88p2 6At0 -65t2 9Ar0 88p2 6At0 B8r0 57p2 -65t2 9Ar0 88p2 6At0 B8k5 57p2 -65t2 9Ar0 88p2 6At0 B7o1 57p2 -65t2 9Ar0 88p2 6At0 48s1 B8s3 -65t2 9Ar0 88p2 6At0 B7l5 57p2 -65t2 9Ar0 88p2 6At0 48l4 B7l5 -65t2 9Ar0 88p2 6At0 B8n0 57p2 -65t2 9Ar0 88p2 6At0 48r1 B7l5 -65t2 9Ar0 88p2 6At0 9Br3 46o1 -65t2 9Ar0 88p2 6At0 B8s3 57p2 -65t2 9Ar0 88p2 6At0 48r2 B8u0 -65t2 9Ar0 78k4 6Bq0 -65t2 9Ar0 59o4 6Bt1 -65t2 9Ar0 59o4 6Bt1 3Bm1 77u0 -65t2 9Ar0 59o4 6Bt1 3Br0 77u0 -65t2 9Ar0 59o4 6Bt1 94l7 39s3 -65t2 9Ar0 59o4 6Bt1 3Bp0 77u0 -65t2 9Ar0 59o4 6Bt1 3Bs3 77u0 -65t2 9Ar0 77q2 A6l5 -65t2 9Ar0 68p3 6At3 -65t2 9Ar0 68s0 6Ap2 -65t2 9Ar0 78s2 5Aq0 -65t2 9Ar0 58o1 6Bs1 -65t2 9Ar0 79q1 B7l0 -65t2 9Ar0 78u0 5Aq0 -65t2 9Ar0 97l6 B7l5 -65t2 9Ar0 97o7 67l6 -65t2 9Ar0 68r3 5Ak2 -65t2 9Ar0 79k1 8Bl6 -65t2 9Ar0 77l4 97l1 -65t2 9Ar0 78o6 6As0 -65t2 9Ar0 87m7 A6k4 -65t2 9Ar0 A5k6 B7s1 -65t2 9Ar0 A5l6 77o4 -65t2 9Ar0 A5o2 77o4 -65t2 9Ar0 95o3 77o4 -65t2 9Ar0 78o1 6Bq0 -65t2 9Ar0 59l1 6Bn2 -65t2 9Ar0 58k5 6Bl3 -65t2 9Ar0 87n6 6Ap2 -65t2 9Ar0 87s1 A6k4 -65t2 9Ar0 88m2 6Au0 -65l6 8Ao3 -65l6 8Ao3 78r2 5Ak1 -65l6 8Ao3 98r0 68s2 -65l6 8Ao3 97t5 B7k4 -65l6 8Ao3 87r2 68s2 -65l6 8Ao3 95o6 49l7 -65l6 8Ao3 78s1 B7l5 -65l6 8Ao3 98s0 68s2 -65l6 8Ao3 98s3 68s2 -65l6 8Ao3 96r2 C8s2 -65l6 8Ao3 A5o2 C9s0 -65l6 8Ao3 A5o7 49l7 -65l6 8Ao3 96t6 B7k4 -65l6 8Ao3 97s1 B7j0 -65l6 8Ao3 95k2 49k7 -65l6 8Ao3 A5k3 B7l4 -65l6 8Ao3 A7o7 68t2 -65l6 8Ao3 58u0 5Ar3 -65l6 8Ao3 68p2 4Bq0 -65l6 8Ao3 A7q3 68s2 -65l6 8Ao3 97m0 A8l1 -55s0 9Bl3 -55s0 9Bl3 87u0 68o1 -55s0 9Bl3 87t1 69k0 -55s0 9Bl3 87t2 69k0 -55s0 9Bl3 88t3 68k5 -55s0 9Bl3 87o4 68k5 -55s0 9Bl3 78o0 B8k1 -55s0 9Bl3 78o0 B8k1 5Bl1 94p3 -55s0 9Bl3 78o0 B8k1 5Bt4 94p3 -55s0 9Bl3 88t0 68k5 -55s0 9Bl3 87t5 68o1 -55s0 9Bl3 87t7 B8p4 -55s0 9Bl3 87t7 B8p4 6Al4 85n6 -55s0 9Bl3 87t7 B8p4 A5o6 4Aq0 -55s0 9Bl3 87t7 B8p4 B5o7 4Aq0 -55s0 9Bl3 87t7 B8p4 A5u0 4Aq0 -55s0 9Bl3 78u0 59p0 -55s0 9Bl3 78t6 59p0 -55s0 9Bl3 87m0 68k5 -55s0 9Bl3 88p2 68k5 -55s0 9Bl3 79o5 B8k1 -55s0 9Bl3 79o5 B8k1 5Bt4 94p3 -55s0 9Bl3 79o5 B8k1 A6l3 5Br3 -55s0 9Bl3 79o5 B8k1 95l7 5Bt7 -55s0 9Bl3 79o5 B8k1 95p2 B4s0 -55s0 9Bl3 78t5 59p0 -55s0 9Bl3 87k7 69k0 -55s0 9Bl3 88n2 68k5 -55s0 9Bl3 87n6 68k5 -55s0 9Bl3 88m2 68k5 -55s0 9Bl3 97q1 69k0 -55s0 9Bl3 97q1 69k0 B9k5 CCq1 -55s0 9Bl3 97q1 69k0 B9t3 74q2 -55s0 9Bl3 97q1 69k0 B9r0 CBs1 -55s0 9Bl3 97q1 69k0 B9p4 74q2 -55s0 9Bl3 86t6 69k0 -55s0 9Bl3 79k1 5Bt7 -55s0 9Bl3 88k2 B7k5 -55s0 9Bl3 87m7 69k0 -55s0 9Bl3 78k4 5Bp0 -55s0 9Bl3 86r2 69k0 -55s0 9Bl3 88p4 68o1 -55s0 9Bl3 78m3 4Ao6 -55s0 9Bl3 78m3 4Ao6 B9l6 57t3 -55s0 9Bl3 78m3 4Ao6 A9p3 BBr2 -55s0 9Bl3 87l0 68k5 -55s0 9Bl3 68l4 5Br3 -55p0 A9t6 -55p0 A9t6 78u0 7Al6 -55p0 A9t6 87o3 69k7 -55p0 A9t6 87o6 A6r0 -55p0 A9t6 78t6 7Al6 -55p0 A9t6 97o2 69k7 -55p0 A9t6 97o7 A6r0 -55p0 A9t6 86r2 A6l1 -55p0 A9t6 78s2 7Al6 -55p0 A9t6 78t2 7Al6 -55p0 A9t6 86t6 B5l5 -55p0 A9t6 87u0 79p2 -55p0 A9t6 87k7 69k7 -55p0 A9t6 88l5 86s0 -55p0 A9t6 79l1 86s0 -55p0 A9t6 88k5 86s0 -55p0 A9t6 86t3 B5l5 -55p0 A9t6 87t2 B5q3 -55p0 A9t6 87t4 79p2 -55p0 A9t6 85t4 A6l1 -55p0 A9t6 97k3 B6s3 -55p0 A9t6 87r1 79p2 -55p0 A9t6 97q3 B5l5 -55p0 A9t6 87n6 79p2 -55p0 A9t6 87m6 79p2 -55p0 A9t6 85s0 A6l1 -65o6 99l6 -65o6 99l6 A6r1 B7t5 -65o6 99l6 A6t5 B7s1 -65o6 99l6 A6k7 C8o7 -65o6 99l6 A7l5 CAs2 -65o6 99l6 A6s1 C8r2 -65o6 99l6 A6m7 B7r2 -65o6 99l6 B6l3 B7r2 -65o6 99l6 97u0 B8o5 -65o6 99l6 A6l0 B7s1 -65o6 99l6 A6n6 C8q1 -65o6 99l6 96r2 B7s1 -65o6 99l6 96l7 57r3 -65o6 99l6 97l3 58t5 -65o6 99l6 87t1 A7o5 -65o6 99l6 B6k6 C8k3 -65o6 99l6 A7n2 C8q1 -65o6 99l6 A7m2 C8t6 -65o6 99l6 97t4 B7k4 -65o6 99l6 97t7 B8m1 -65o6 99l6 A5s2 B7k0 -65o6 99l6 A5l7 B7r2 -65o6 99l6 87s1 A7o5 -65o6 99l6 87r2 A7o5 -65o6 99l6 A6t1 C8r2 -65o6 99l6 A7r3 C8s2 -65o6 99l6 A7k2 77s1 -65o6 99l6 97m3 B7k0 -65o6 99l6 98q1 5At6 -57o4 99l1 -57o4 99l1 6Ar1 7Bt2 -57o4 99l1 6At2 7Bs2 -57o4 99l1 6Ak4 8Co4 -57o4 99l1 6As2 8Cr2 -57o4 99l1 6An1 8Cq1 -57o4 99l1 6Am4 8Cq1 -57o4 99l1 6Bl0 7Br2 -57o4 99l1 69r2 7Bs2 -57o4 99l1 6Al3 7Bs2 -57o4 99l1 7Al2 ACt1 -57o4 99l1 69l4 95r1 -57o4 99l1 79l0 85t2 -57o4 99l1 79u0 7Bk7 -57o4 99l1 78t6 7Ao2 -57o4 99l1 6Bk1 8Cs2 -57o4 99l1 7An0 8Cq1 -57o4 99l1 7Am5 8Ct1 -57o4 99l1 79t4 7Bk7 -57o4 99l1 79t7 7Bk7 -57o4 99l1 5As1 8Cs2 -57o4 99l1 5Al4 7Br2 -57o4 99l1 6At6 8Cr2 -57o4 99l1 7Ar0 8Cs1 -57o4 99l1 89q1 A5t1 -65k2 99l6 -65k2 99l6 A6r1 B7s1 -65k2 99l6 A6t5 B7s1 -65k2 99l6 A7l5 CAt6 -65k2 99l6 A6n6 C8q1 -65k2 99l6 A6s1 B7s1 -65k2 99l6 A6m7 B7r2 -65k2 99l6 96r2 B7s1 -65k2 99l6 87r2 A7o5 -65k2 99l6 A6o3 57s3 -65k2 99l6 B6o2 C8s2 -65k2 99l6 A7n2 C8q1 -65k2 99l6 A5s2 B7k0 -65k2 99l6 A6l0 B7s1 -65k2 99l6 87s1 A7o5 -65k2 99l6 98q1 5At5 -65k2 99l6 A7r3 C8s2 -65k2 99l6 A7m2 C8t6 -65k2 99l6 A5l7 B7r2 -65k2 99l6 A6t1 C8r2 -55t0 AAu0 -55t0 AAu0 77u0 69o3 -55t0 AAu0 86u0 88o2 -55t0 AAu0 78p4 7Al6 -55t0 AAu0 68r1 88o5 -55t0 AAu0 68u0 88o5 -55t0 AAu0 86p3 C7s2 -55t0 AAu0 86p3 C7s2 C4l6 7At2 -55t0 AAu0 86p3 C7s2 B5l2 79t6 -55t0 AAu0 86p3 C7s2 8Ak1 A4k6 -55t0 AAu0 86p3 C7s2 8Aq1 A4r0 -55t0 AAu0 86p3 C7s2 89u0 7Br0 -55t0 AAu0 68p0 7Al6 -55t0 AAu0 68s2 88o5 -55t0 AAu0 86s1 A7l1 -55t0 AAu0 86s1 A7l1 8Ak1 A3k6 -55t0 AAu0 86s1 A7l1 B4u0 84s1 -55t0 AAu0 86s1 A7l1 B5r0 84k3 -55t0 AAu0 86s1 A7l1 88q2 7Ar3 -55t0 AAu0 86s1 A7l1 6Al0 7Ck3 -55t0 AAu0 86r1 88o2 -55t0 AAu0 58r3 7Cr1 -55t0 AAu0 85r0 C7r1 -55t0 AAu0 77r1 69o3 -55t0 AAu0 77o3 B6o1 -55t0 AAu0 77s2 69k7 -55t0 AAu0 87p2 A7l1 -55t0 AAu0 78s0 A7r1 -55t0 AAu0 87s3 7Ar1 -55t0 AAu0 77s1 96k4 -55t0 AAu0 87k6 A7r0 -55t0 AAu0 78k1 7Ar3 -55t0 AAu0 77o0 6Bo6 -55t0 AAu0 78p2 6Bl2 -55t0 AAu0 87s0 B6l5 -55t0 AAu0 78s3 97t2 -55t0 AAu0 78r0 97t2 -55t0 AAu0 87r3 B6l5 -55t0 AAu0 67r2 79o7 -55t0 AAu0 67q2 96q2 -55t0 AAu0 87r0 7Ar1 -75k6 AAt2 -75k6 AAt2 98s2 7Ar3 -75k6 AAt2 A8l2 78p3 -75k6 AAt2 A8p2 88n0 -75o2 9At4 -75o2 9At4 69l1 87o3 -75o2 9At4 78l5 6Ar3 -75o2 9At4 98r0 78n0 -75o2 9At4 A5p4 97l1 -75o2 9At4 A5s2 B7l0 -75o2 9At4 A5t3 B7s1 -75o2 9At4 89l0 6As3 -75o2 9At4 58r2 79l0 -75o2 9At4 58t1 79l0 -75o2 9At4 58t2 79l0 -75o2 9At4 58r1 87m0 -75o2 9At4 A5r0 B7s1 -75o2 9At4 A5t6 77l4 -75o2 9At4 A5s3 B7r2 -75o2 9At4 58s1 77l4 -75o2 9At4 98k2 78n0 -75o2 9At4 A6t1 87m0 -75o2 9At4 58p3 5Bl7 -75o2 9At4 69q1 6Al6 -75o2 9At4 58s2 79l0 -75o2 9At4 47q2 87m0 -75o2 9At4 98s0 78m0 -75o2 9At4 98l2 78n0 -75o2 9At4 A7l3 59o6 -75o2 9At4 98l1 87m0 -75o2 9At4 A6m7 87m0 -75o2 9At4 A7l5 77p3 -75o2 9At4 A7k5 77p3 -75o2 9At4 98n2 78m0 -75o2 9At4 97n6 78m0 -56s2 A9r3 -56s2 A9r3 79n0 7Bk3 -56s2 A9r3 86k7 B6n0 -56s2 A9r3 94l6 76p0 -56s2 A9r3 78p3 A5o1 -56s2 A9r3 79t3 7Bk7 -56s2 A9r3 79m5 7Bk3 -56s2 A9r3 78t4 7As0 -56s2 A9r3 96o7 B6n0 -56s2 A9r3 87p2 A6t3 -56s2 A9r3 86t7 A6t3 -56s2 A9r3 79r0 7Bk7 -56s2 A9r3 78n6 6Ao3 -56s2 A9r3 77l7 A6p4 -56s2 A9r3 79p4 7Bk7 -56s2 A9r3 78o1 7Bn2 -56s2 A9r3 86t4 6Ak7 -56s2 A9r3 77t6 6Al2 -56s2 A9r3 94o7 76p0 -56s2 A9r3 85l2 76p0 -56s2 A9r3 6Ak1 8Cq1 -56s2 A9r3 69o0 7Bs2 -56s2 A9r3 86r1 7At3 -56s2 A9r3 86t5 A5l5 -56s2 A9r3 6Al0 76l1 -56s2 A9r3 86m6 7Ap2 -56s2 A9r3 86n6 7Ap2 -56s2 A9r3 78t1 6Al2 -56s2 A9r3 78t2 6Al2 -56s2 A9r3 94o2 76p0 -56s2 A9r3 87k5 7As0 diff --git a/backend/piece.h b/backend/piece.h deleted file mode 100644 index 8fb7017..0000000 --- a/backend/piece.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PIECE_H_ -#define PIECE_H_ - -struct Position { - int x, y; -}; - -struct Piece { - int id; - int size; - Position coords[5]; - int nedge[4]; - Position edges[4][3]; - int minx, miny, maxx, maxy; -}; - -struct Rotation { - int offset_x, offset_y; - Piece *piece; -}; - -struct Block { - int id; - int size; - Piece *variations[9]; - Rotation rotations[8]; - char name() { return 'u' - (id >> 3); } -}; - -extern Block *block_set[]; - -#endif // PIECE_H_ diff --git a/backend/piece.rb b/backend/piece.rb deleted file mode 100755 index 1c79ff3..0000000 --- a/backend/piece.rb +++ /dev/null @@ -1,250 +0,0 @@ -#!/usr/local/bin/ruby - -class Piece - attr_reader :id, :name, :coords, :edges, :directed_edges - - def initialize(id, name, coords) - @id = id - @name = name - @coords = coords - @edges = coords.reject{|x,y| - coords.include?([x-1,y]) && coords.include?([x+1,y]) || - coords.include?([x,y-1]) && coords.include?([x,y+1]) - } - @directed_edges = [ - @edges.reject{|x,y| coords.include?([x,y-1]) || coords.include?([x-1,y])}, - @edges.reject{|x,y| coords.include?([x,y-1]) || coords.include?([x+1,y])}, - @edges.reject{|x,y| coords.include?([x,y+1]) || coords.include?([x-1,y])}, - @edges.reject{|x,y| coords.include?([x,y+1]) || coords.include?([x+1,y])} - ] - end - - def blk_name - @name[0..-2] - end - - def size - @coords.size - end - - def min_x - @coords.map{|x,y| x}.min - end - - def min_y - @coords.map{|x,y| y}.min - end - - def max_x - @coords.map{|x,y| x}.max - end - - def max_y - @coords.map{|x,y| y}.max - end - - def contour - start = pt = coords.min - contour = [pt] - - dir = [1,0] # east - pt = vec_add(pt, dir) - until pt == start - contour << pt - if coords.include?(vec_add(pt, leftside(dir))) - dir = [dir[1], -dir[0]] # turn left - elsif !coords.include?(vec_add(pt, rightside(dir))) - dir = [-dir[1], dir[0]] # turn right - end - pt = vec_add(pt, dir) - end - contour - end - - def to_s - s = (0..4).map{" "} - minx, miny = min_x, min_y - @coords.each{|x,y| s[y-miny][x-minx] = (x==0 && y==0) ? ?@ : ?#} - s.map{|l| l.rstrip.empty? ? "" : l.rstrip + "\n"}*'' - end - - private - def vec_add(v1, v2) - v1.zip(v2).map{|x,y| x+y} - end - - def leftside(dir) - case dir - when [ 0,-1]; [-1,-1] - when [ 1, 0]; [ 0,-1] - when [ 0, 1]; [ 0, 0] - when [-1, 0]; [-1, 0] - end - end - - def rightside(dir) - leftside([-dir[1], dir[0]]) - end -end - -class Bloku - attr_reader :id, :name, :size - include Enumerable - - def initialize(id, name, *coords) - @id = id - @name = name - @size = coords.size - make_variations(coords) - end - - def rotate(x, y, dir) - dx, dy, piece = @rotations[dir] - [x+dx, y+dy, piece] - end - - def each(&block) - @variations.each(&block) - end - - private - def find_overlap(p2) - @variations.each do |p1| - mx1, my1, mx2, my2 = p1.min_x, p1.min_y, p2.min_x, p2.min_y - if p1.coords.sort.zip(p2.coords.sort).all? {|c1, c2| - x1, y1 = *c1 - x2, y2 = *c2 - x1-mx1 == x2-mx2 && y1-my1 == y2-my2 - } - return [mx2-mx1, my2-my1, p1] - end - end - nil - end - - def make_variations(coords) - @variations = [] - @rotations = [] - h = {} - 8.times do |i| - piece = Piece.new(@id << 3|i, "#{@name}#{i}", coords.dup) - synonym = find_overlap(piece) - if synonym - @rotations << synonym - else - @rotations << [0, 0, piece] - @variations << piece - end - coords.map!{|x,y| [-x, y]} # mirror - coords.map!{|x,y| [-y, x]} if i%2 == 1 # rotate right - end - end -end - -class BlokuSet - BLOKU_SET = - [ - Bloku.new(0, 'u', [0,0], [1,0], [0,1], [-1,0], [0,-1]), # X5 - Bloku.new(1, 't', [-1,-1], [-1,0], [0,0], [1,0], [0,1]), # F5 - Bloku.new(2, 's', [0,0], [1,0], [1,1], [-1,0], [-1,-1]), # Z5 - Bloku.new(3, 'r', [0,0], [1,0], [1,1], [0,-1], [-1,-1]), # W5 - Bloku.new(4, 'q', [0,0], [1,0], [2,0], [0,-1], [0,-2]), # V5 - Bloku.new(5, 'p', [0,0], [0,-1], [0,1], [-1,1], [1,1]), # T5 - Bloku.new(6, 'o', [0,-1], [0,0], [1,0], [0,1], [0,2]), # Y5 - Bloku.new(7, 'n', [0,0], [0,1], [-1,1], [0,-1], [-1,-1]), # C5 - Bloku.new(8, 'm', [0,-1], [-1,0], [0,0], [-1,1], [0,1]), # P5 - Bloku.new(9, 'l', [0,-2], [0,-1], [0,0], [-1,0], [-1,1]), # N5 - Bloku.new(10, 'k', [0,0], [0,1], [0,-2], [0,-1], [-1,1]), # L5 - Bloku.new(11, 'j', [0,0], [0,1], [0,2], [0,-1], [0,-2]), # I5 - - Bloku.new(12, 'i', [-1,0], [0,0], [0,1], [1,1]), # Z4 - Bloku.new(13, 'h', [0,0], [1,0], [0,1], [1,1]), # O4 - Bloku.new(14, 'g', [0,0], [1,0], [0,1], [0,-1]), # T4 - Bloku.new(15, 'f', [0,0], [0,-1], [0,1], [-1,1]), # L4 - Bloku.new(16, 'e', [0,0], [0,1], [0,2], [0,-1]), # I4 - - Bloku.new(17, 'd', [0,0], [1,0], [0,-1]), # L3 - Bloku.new(18, 'c', [0,0], [0,1], [0,-1]), # I3 - - Bloku.new(19, 'b', [0,0], [0,1]), # I2 - Bloku.new(20, 'a', [0,0]), # I1 - ] - - NBLOKU = BLOKU_SET.size - - BLOKU_BIT = {} - NBLOKU.times {|i| BLOKU_BIT[BLOKU_SET[i].name] = 1 << i} - - NAME_TO_BLK = {} - BLOKU_SET.each {|blk| NAME_TO_BLK[blk.name] = blk} - NBLOKU.times {|i| NAME_TO_BLK[i] = BLOKU_SET[i]} - - def BlokuSet.[](blk) - NAME_TO_BLK[blk] - end - - include Enumerable - - def initialize(vec = (1 << NBLOKU) - 1) - @vec = vec - end - - def each - NBLOKU.times do |i| - yield BLOKU_SET[i] if @vec & 1 << i != 0 - end - end - - def delete(blk_name) - BlokuSet.new(@vec & ~BLOKU_BIT[blk_name]) - end - - def each_piece(&block) - each {|blk| blk.each(&block) } - end -end - -def to_c(obj) - if obj.kind_of?(Array) - '{' + obj.map{|x| to_c(x) }.join(',') + '}' - else - obj.to_s - end -end - -def compile - puts '#include ' - puts '#include "piece.h"' - puts - bloku_set = BlokuSet.new - bloku_set.each_with_index do |blk, i| - blk.each do |piece| - name = piece.name.tr('.','_') - id = (i << 3) + name[-1,1].to_i - fs = ["0x%02x"%id, piece.size, to_c(piece.coords), - to_c(piece.directed_edges.map(&:size)), - to_c(piece.directed_edges), - piece.min_x, piece.min_y, piece.max_x, piece.max_y] - puts "static Piece #{name} = {#{fs * ', '}};" - end - end - bloku_set.each_with_index do |blk, i| - name = blk.name.delete('.') - puts "static Block #{name} = {" - puts " 0x#{"%02x"%[i<<3]}, #{blk.size}," - puts " { #{blk.map{|p|'&'+p.name.tr('.','_')}*', '}, NULL }," - rot = (0...8).map{|dir| dx,dy,piece = blk.rotate(0,0,dir) - "{#{dx},#{dy},&#{piece.name.tr('.','_')}}" - } * ', ' - puts " { #{rot} }" - puts "};" - end - puts "Block *block_set[] = {" - names = bloku_set.map{|blk| '&'+blk.name.delete('.')} * ', ' - puts " #{names}" - puts "};" -end - -if $0 == __FILE__ - compile -end diff --git a/backend/probcut.h b/backend/probcut.h deleted file mode 100644 index eab6ae2..0000000 --- a/backend/probcut.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef PROBCUT_H_ -#define PROBCUT_H_ - -#define PROBCUT_MIN_HEIGHT 3 -#define PROBCUT_MAX_HEIGHT 10 -#define PROBCUT_MAX_TURN 24 - -struct ProbCut { - int depth; - double a, b, sigma; -}; - -const ProbCut probcut_table[PROBCUT_MAX_TURN+1][PROBCUT_MAX_HEIGHT] = { -#include "probcut.tab.c" -}; - -inline const ProbCut* probcut_entry(int turn, int depth) -{ - if (depth < PROBCUT_MIN_HEIGHT || depth > PROBCUT_MAX_HEIGHT || - turn > PROBCUT_MAX_TURN) - return NULL; - const ProbCut* pc = &probcut_table[turn][depth - PROBCUT_MIN_HEIGHT]; - if (pc->depth == 0) - return NULL; - return pc; -} - -#endif // PROBCUT_H_ diff --git a/backend/probcut.tab.c b/backend/probcut.tab.c deleted file mode 100644 index 16f756b..0000000 --- a/backend/probcut.tab.c +++ /dev/null @@ -1,250 +0,0 @@ -{ /* turn 0 */ - { 0, 0, 0, 0 }, // 3 - { 0, 0, 0, 0 }, // 4 - { 0, 0, 0, 0 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 1 */ - { 1, 0.914439, 5.010248, 2.534777 }, // 3 - { 2, 0.971216, -1.764340, 1.344761 }, // 4 - { 1, 0.773585, 2.019473, 1.754227 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 2 */ - { 1, 0.653619, 12.462249, 3.763815 }, // 3 - { 2, 0.689542, -2.303912, 2.194905 }, // 4 - { 1, 0.601083, 10.710842, 2.718988 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 3 */ - { 1, 0.556871, 2.001865, 3.473129 }, // 3 - { 2, 0.661311, -11.312044, 2.535464 }, // 4 - { 1, 0.403787, 1.284452, 3.726605 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 4 */ - { 1, 0.480933, 17.839868, 3.969265 }, // 3 - { 2, 0.596093, -3.558592, 3.125120 }, // 4 - { 1, 0.383468, 16.403460, 3.935307 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 5 */ - { 1, 0.415710, 4.466374, 3.953322 }, // 3 - { 2, 0.487554, -15.242358, 3.668335 }, // 4 - { 1, 0.312029, 2.088815, 4.659717 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 6 */ - { 1, 0.463349, 15.746612, 4.196071 }, // 3 - { 2, 0.629353, -1.128563, 3.550839 }, // 4 - { 1, 0.337845, 15.220442, 4.877776 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 7 */ - { 1, 0.556226, 0.837416, 4.006479 }, // 3 - { 2, 0.622491, -9.043782, 3.612598 }, // 4 - { 1, 0.416287, 0.570459, 4.867491 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 8 */ - { 1, 0.512031, 11.613398, 4.723482 }, // 3 - { 2, 0.626605, -2.462664, 3.759353 }, // 4 - { 1, 0.310527, 14.018288, 5.248645 }, // 5 - { 0, 0, 0, 0 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 9 */ - { 1, 0.548116, 1.638224, 4.362050 }, // 3 - { 2, 0.663708, -6.269214, 3.806463 }, // 4 - { 1, 0.446401, 0.609348, 5.292276 }, // 5 - { 2, 0.644511, -2.392467, 4.384093 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 10 */ - { 1, 0.617311, 6.099897, 4.253820 }, // 3 - { 2, 0.682351, -1.755026, 4.381228 }, // 4 - { 1, 0.523809, 3.503658, 4.618784 }, // 5 - { 2, 0.594739, -0.968245, 5.019895 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 11 */ - { 1, 0.589443, 0.361246, 4.419280 }, // 3 - { 2, 0.686327, -3.474987, 3.479470 }, // 4 - { 1, 0.467658, -1.030979, 5.116754 }, // 5 - { 2, 0.646278, -1.813651, 4.442251 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 12 */ - { 1, 0.639371, 3.546646, 4.120514 }, // 3 - { 2, 0.792836, -0.044757, 3.646193 }, // 4 - { 1, 0.560421, 1.728863, 5.303942 }, // 5 - { 2, 0.743740, 0.544342, 4.729497 }, // 6 - { 0, 0, 0, 0 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 13 */ - { 1, 0.727154, -0.815885, 4.372574 }, // 3 - { 2, 0.833467, -0.447807, 3.697003 }, // 4 - { 1, 0.592634, -2.207965, 5.322457 }, // 5 - { 2, 0.779354, -0.156051, 4.633574 }, // 6 - { 3, 0.903000, -2.498106, 3.376799 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 14 */ - { 1, 0.671774, 2.548782, 4.420456 }, // 3 - { 2, 0.861281, 0.773342, 3.399364 }, // 4 - { 1, 0.572733, 2.528155, 5.167625 }, // 5 - { 2, 0.814715, 1.309779, 3.925784 }, // 6 - { 3, 0.902688, -1.667189, 3.300271 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 15 */ - { 1, 0.784786, -1.372773, 4.247711 }, // 3 - { 2, 0.881729, -0.615118, 2.977631 }, // 4 - { 1, 0.716406, -2.352405, 4.651760 }, // 5 - { 2, 0.843852, -0.368530, 3.509034 }, // 6 - { 3, 0.905738, -1.866567, 3.739858 }, // 7 - { 0, 0, 0, 0 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 16 */ - { 1, 0.745530, 1.878032, 3.867225 }, // 3 - { 2, 0.907313, 0.307068, 2.690935 }, // 4 - { 1, 0.677437, 1.460581, 4.448741 }, // 5 - { 2, 0.899764, 0.595826, 3.738312 }, // 6 - { 3, 0.929263, -2.008574, 4.279258 }, // 7 - { 4, 1.032309, 1.508289, 4.317734 }, // 8 - { 0, 0, 0, 0 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 17 */ - { 1, 0.885816, -0.946493, 2.921153 }, // 3 - { 2, 0.931367, 0.238675, 2.595024 }, // 4 - { 1, 0.881951, -1.934992, 4.001337 }, // 5 - { 2, 0.921980, 1.074401, 4.598717 }, // 6 - { 3, 0.994030, -2.475349, 4.696014 }, // 7 - { 4, 1.045893, 2.928866, 4.928478 }, // 8 - { 3, 1.035549, -3.069185, 6.522175 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 18 */ - { 1, 0.844709, 0.613295, 3.296104 }, // 3 - { 2, 0.924675, 0.335186, 3.107028 }, // 4 - { 1, 0.833179, -0.912049, 4.798669 }, // 5 - { 2, 0.930855, 1.292228, 4.872751 }, // 6 - { 3, 0.998347, -3.537523, 4.859171 }, // 7 - { 4, 1.101732, 1.231883, 4.776032 }, // 8 - { 3, 1.039513, -5.082785, 6.642631 }, // 9 - { 0, 0, 0, 0 }, // 10 -}, -{ /* turn 19 */ - { 1, 0.914728, -0.930556, 3.443570 }, // 3 - { 2, 0.923858, -0.126472, 3.837933 }, // 4 - { 1, 0.821073, -2.108271, 5.410021 }, // 5 - { 2, 0.889020, 0.826062, 5.330143 }, // 6 - { 3, 1.018980, -2.302590, 5.129224 }, // 7 - { 4, 1.076589, 2.956434, 5.086840 }, // 8 - { 3, 1.122534, -3.498098, 7.228481 }, // 9 - { 4, 1.231913, 6.278205, 7.223916 }, // 10 -}, -{ /* turn 20 */ - { 1, 0.820770, 0.848200, 4.505243 }, // 3 - { 2, 0.962888, 0.749995, 3.657272 }, // 4 - { 1, 0.766003, -0.270508, 6.030184 }, // 5 - { 2, 1.024503, 1.275592, 5.500166 }, // 6 - { 3, 1.024778, -3.629072, 5.315162 }, // 7 - { 4, 1.209232, 0.875989, 4.958280 }, // 8 - { 3, 1.151721, -6.947804, 7.558996 }, // 9 - { 4, 1.373412, 1.197335, 7.162778 }, // 10 -}, -{ /* turn 21 */ - { 1, 0.959430, -1.687087, 3.885856 }, // 3 - { 2, 0.958575, 1.066731, 3.600335 }, // 4 - { 1, 0.964307, -2.840552, 5.536590 }, // 5 - { 2, 0.993925, 2.404281, 5.740936 }, // 6 - { 3, 1.139347, -2.217344, 5.353062 }, // 7 - { 4, 1.246947, 4.376531, 5.435883 }, // 8 - { 3, 1.290253, -3.421059, 7.604233 }, // 9 - { 4, 1.440688, 7.591201, 7.385451 }, // 10 -}, -{ /* turn 22 */ - { 1, 0.913701, -1.294190, 4.055791 }, // 3 - { 2, 1.037619, 0.574351, 3.319788 }, // 4 - { 1, 0.949178, -3.111209, 6.059885 }, // 5 - { 2, 1.131928, 1.339923, 5.595295 }, // 6 - { 3, 1.238483, -5.368266, 5.329220 }, // 7 - { 4, 1.278519, 1.119709, 5.772418 }, // 8 - { 3, 1.424573, -8.995177, 7.541452 }, // 9 - { 4, 1.468075, 1.395277, 7.593006 }, // 10 -}, -{ /* turn 23 */ - { 1, 1.046455, -1.147245, 3.402233 }, // 3 - { 2, 1.067518, 1.504563, 3.326585 }, // 4 - { 1, 1.091576, -2.751017, 5.831246 }, // 5 - { 2, 1.182816, 3.498986, 5.885976 }, // 6 - { 3, 1.209168, -2.391792, 6.262995 }, // 7 - { 4, 1.329745, 5.277817, 5.495753 }, // 8 - { 3, 1.382363, -2.989175, 8.163535 }, // 9 - { 4, 1.489314, 8.148166, 7.079100 }, // 10 -}, -{ /* turn 24 */ - { 1, 1.009127, -1.800161, 3.617773 }, // 3 - { 2, 1.088475, 0.567545, 4.262085 }, // 4 - { 1, 1.108204, -4.552575, 6.458191 }, // 5 - { 2, 1.203174, 1.135609, 6.970049 }, // 6 - { 3, 1.317639, -6.564177, 6.097280 }, // 7 - { 4, 1.332536, 0.294527, 5.190226 }, // 8 - { 3, 1.464396, -9.687105, 7.930027 }, // 9 - { 4, 1.433802, -0.014043, 6.071555 }, // 10 -}, diff --git a/backend/search.cpp b/backend/search.cpp deleted file mode 100644 index e34ab95..0000000 --- a/backend/search.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "board.h" -#include "search.h" -using namespace std; - -#define USE_PROBCUT -#undef PROBSTAT - -#ifdef USE_PROBCUT -#include "probcut.h" -#endif - -#define CHECKPOINT_INTERVAL 10000 - -int visited_nodes; -static int check_point; -static clock_t expire_clock; -static bool enable_timeout; -bool quiet = false; -static bool timed_out; - -typedef map > Hash; - -struct Child { - Child(Board& b, Move m, Hash* hash); - bool operator<(const Child& rhs) const { - return score < rhs.score; - } - Board board; - int score; - Move move; -}; - -Child::Child(Board& b, Move m, Hash* hash) : - board(b.child(m)), move(m) -{ - Hash::iterator i = hash->find(BoardMapKey(board)); - if (i != hash->end()) { - int a = i->second.first; - int b = i->second.second; - if (a > -INT_MAX && b < INT_MAX) - score = (a + b) / 2 - 1000; - else - score = board.nega_eval(); - } - else - score = board.nega_eval(); -} - -class AlphaBetaVisitor : public MovableVisitor { -public: - AlphaBetaVisitor(Board* n, int a, int b) - : node(n), alpha(a), beta(b) {} - virtual bool visit_move(Move move); - - Board* node; - int alpha; - int beta; -}; - -bool AlphaBetaVisitor::visit_move(Move m) -{ - visited_nodes++; - int v = -node->child(m).nega_eval(); - if (v > alpha) { - alpha = v; - if (alpha >= beta) - return false; - } - return true; -} - -inline double round_(double num) -{ - if (num < 0.0) - return ceil(num - 0.5); - else - return floor(num + 0.5); -} - -int negascout(Board* node, int depth, int alpha, int beta, - Move *best_move, Hash* hash, Hash* prev_hash, int hash_depth) -{ - assert(alpha <= beta); - - if (++visited_nodes >= check_point && enable_timeout) { - if ((int)(expire_clock - clock()) < 0) { - timed_out = true; - return 0; - } - check_point += CHECKPOINT_INTERVAL; - } - - if (depth <= 1) { - AlphaBetaVisitor visitor(node, alpha, beta); - if (node->each_movable(&visitor)) - return visitor.alpha; - else - return visitor.beta; - } - - pair* hash_entry = NULL; - if (hash_depth > 0) { - pair found = - hash->insert(make_pair(BoardMapKey(*node), - make_pair(-INT_MAX, INT_MAX))); - hash_entry = &found.first->second; - if (!found.second) { - int ha = hash_entry->first; - int hb = hash_entry->second; - if (hb <= alpha) return hb; - if (ha >= beta) return ha; - if (ha == hb) return ha; - alpha = max(alpha, ha); - beta = min(beta, hb); - } - } - -#ifdef USE_PROBCUT - - /* ProbCut */ - const ProbCut* pc = probcut_entry(node->turn(), depth); - - if (pc) { - double thresh; - if (node->turn() >= 15) - thresh = 2.0; - else - thresh = 1.6; - - if (beta < INT_MAX) { - int bound = (int)round_((thresh * pc->sigma + beta - pc->b) - / pc->a); - int r = negascout(node, pc->depth, bound-1, bound, - NULL, hash, prev_hash, 0); - if (timed_out) - return 0; - if (r >= bound) - { - if (hash_entry) - hash_entry->first = max(hash_entry->first, beta); - return beta; - } - } - if (alpha > -INT_MAX) { - int bound = (int)round_((-thresh * pc->sigma + alpha - pc->b) - / pc->a); - int r = negascout(node, pc->depth, bound, bound+1, - NULL, hash, prev_hash, 0); - if (timed_out) - return 0; - if (r <= bound) - { - if (hash_entry) - hash_entry->second = min(hash_entry->second, alpha); - return alpha; - } - } - } - -#endif // USE_PROBCUT - - vector children; - { - Move movables[1500]; - int nmove = node->movables(movables); - for (Move* move = movables; move < movables + nmove; move++) - children.push_back(Child(*node, *move, prev_hash+1)); - - sort(children.begin(), children.end()); - } - - bool found_pv = false; - int score_max = -INT_MAX; - int a = alpha; - - for (vector::iterator i = children.begin(); - i != children.end(); ++i) - { - int score; - if (found_pv) { - score = -negascout(&i->board, depth-1, -a-1, -a, NULL, - hash+1, prev_hash+1, hash_depth-1); - if (timed_out) - return 0; - if (score > a && score < beta) { - score = -negascout(&i->board, depth-1, -beta, -score, - NULL, hash+1, prev_hash+1, hash_depth-1); - if (timed_out) - return 0; - } - } - else { - score = -negascout(&i->board, depth-1, -beta, -a, - NULL, hash+1, prev_hash+1, hash_depth-1); - if (timed_out) - return 0; - } - - if (score >= beta) { - if (hash_entry) - hash_entry->first = max(hash_entry->first, score); - return score; - } - - if (score > score_max) { - if (score > a) - a = score; - if (score > alpha) { - found_pv = true; - if (best_move) - *best_move = i->move; - } - score_max = score; - } - } - if (hash_entry) { - if (score_max > alpha) - hash_entry->first = hash_entry->second = score_max; - else - hash_entry->second = min(hash_entry->second, score_max); - } - return score_max; -} - -SearchResult search_negascout(Board* node, int max_depth, - int stop_ms, int timeout_ms) -{ - Move best_move = INVALID_MOVE; - int score; - - clock_t start = clock(); - expire_clock = start + timeout_ms * (CLOCKS_PER_SEC / 1000); - check_point = visited_nodes + CHECKPOINT_INTERVAL; - timed_out = false; - enable_timeout = false; - -#ifdef PROBSTAT - score = negascout(node, 1, -INT_MAX, INT_MAX, NULL, NULL, NULL, 0); - printf("1> ? ???? (%d)\n", score); -#endif - - Hash *prev_hash, *hash; - prev_hash = new Hash[max_depth]; - for (int i = 2; i <= max_depth; i++) { - hash = new Hash[max_depth]; - Move move; - score = negascout(node, i, -INT_MAX, INT_MAX, &move, - hash, prev_hash, 8); - if (timed_out) - break; - double sec = (double)(clock() - start) / CLOCKS_PER_SEC; - if (!quiet) { - printf("%d> %.3f %s (%d)\n", - i, sec, move.fourcc(), score); - } - delete[] prev_hash; - prev_hash = hash; - best_move = move; - enable_timeout = true; - if (sec * 1000 > stop_ms) - break; - } - delete[] prev_hash; - - if (timed_out) - delete[] hash; - - return SearchResult(best_move, score); -} - -typedef map WldHash; - -int wld_rec(Board* node, int alpha, int beta, WldHash* hash) -{ - BoardMapKey key(*node); - WldHash::iterator i = hash->find(key); - if (i != hash->end()) - return node->is_violet() ? i->second : -i->second; - - if (++visited_nodes >= check_point) { - if ((int)(expire_clock - clock()) < 0) - throw Timeout(); - check_point += CHECKPOINT_INTERVAL; - } - - Move movables[1000]; - int nmove = node->movables(movables); - if (movables[0].is_pass()) { - int score = node->nega_score(); - if (score < 0) - return score; - else if (score == 0) { - nmove = node->child(movables[0]).movables(movables); - if (movables[0].is_pass()) - return 0; - else - return -block_set[movables[0].block_id()]->size; - } - } - - for (Move* move = movables; move < movables + nmove; move++) { - Board child = node->child(*move); - int v = -wld_rec(&child, -beta, -alpha, hash+1); - if (v > alpha) { - alpha = v; - if (alpha > 0 || alpha >= beta) - break; - } - } - (*hash)[key] = node->is_violet() ? alpha : -alpha; - return alpha; -} - -SearchResult wld(Board* node, int timeout_sec) -{ - expire_clock = clock() + timeout_sec * CLOCKS_PER_SEC; - check_point = visited_nodes + CHECKPOINT_INTERVAL; - - WldHash hash[42]; - visited_nodes++; - - int alpha = -INT_MAX, beta = INT_MAX; - Move movables[1000]; - int nmove = node->movables(movables); - Move wld_move; - - for (Move* move = movables; move < movables + nmove; move++) { - Board child = node->child(*move); - int v = -wld_rec(&child, -beta, -alpha, hash); - if (v > alpha) { - alpha = v; - wld_move = *move; - if (alpha > 0 || alpha >= beta) - break; - } - } - return SearchResult(wld_move, alpha); -} - -int perfect_rec(Board* node, int npass, int alpha, int beta, WldHash* hash) -{ - BoardMapKey key(*node); - WldHash::iterator i = hash->find(key); - if (i != hash->end()) - return node->is_violet() ? i->second : -i->second; - - visited_nodes++; - - Move movables[1000]; - int nmove = node->movables(movables); - if (movables[0].is_pass()) { - if (++npass >= 2) - return node->nega_score(); - } - else - npass = 0; - - for (Move* move = movables; move < movables + nmove; move++) { - Board child = node->child(*move); - int v = -perfect_rec(&child, npass, -beta, -alpha, hash+1); - if (v > alpha) { - alpha = v; - if (alpha >= beta) { - (*hash)[key] = node->is_violet() ? beta : -beta; - return beta; - } - } - } - (*hash)[key] = node->is_violet() ? alpha : -alpha; - return alpha; -} - -SearchResult perfect(Board* node) -{ - WldHash* hash = new WldHash[44 - node->turn()]; - - visited_nodes++; - - int alpha = -INT_MAX, beta = INT_MAX; - Move movables[1000]; - int nmove = node->movables(movables); - int npass = movables[0].is_pass() ? 1 : 0; - - Move perfect_move; - for (Move* move = movables; move < movables + nmove; move++) { - Board child = node->child(*move); - int v = -perfect_rec(&child, npass, -beta, -alpha, hash); - if (v > alpha) { - alpha = v; - perfect_move = *move; - } - } - delete[] hash; - return SearchResult(perfect_move, alpha); -} - -#if 0 -void wld_test() -{ - const char *moves[] = { - "56t2","9Ao2","39n2","6Dq0","69s2","B8u0","96l7","B5r0","84m3", - "85m7","D7p3","44l7","43k7","17k4","C4r0","EAn0","1Co5","3Ej2", - "12g0","72p4","99c2","A1i1","E1q3","3Bt0","CAu0", NULL - }; - Board b; - for (int i = 0; moves[i]; i++) - b.do_move(Move(moves[i])); - - b.show(); - - try { - for (int npass = 0; npass < 2;) { - clock_t start = clock(); - visited_nodes = 0; - - SearchResult result = wld(&b, 5); - Move m = result.first; - - double sec = (double)(clock() - start) / CLOCKS_PER_SEC; - printf("time(%d): %d nodes / %.3f sec (%d nps)\n", - b.turn(), visited_nodes, sec, (int)(visited_nodes / sec)); - printf("\n%s (%d)\n", m.fourcc(), result.second); - - npass = m.is_pass() ? npass+1 : 0; - b.do_move(m); - b.show(); - } - } - catch (Timeout& e) { - printf("timeout\n"); - } -} - -void perfect_test() -{ - const char *moves[] = { - "46k4","9Ao7","86o7","5Cn1","A8n1","CAt6","5Am3","77m6","7Bq2", - "8Cq2","D9r0","3Dk1","2At2","CEl2","CCp3","B8a0","D6s0","D7b2", - "A4u0","B6d1","C3l1","----","16j0","----","AEg6","----","81i0", - "----", NULL - }; - Board b; - for (int i = 0; moves[i]; i++) - b.do_move(Move(moves[i])); - - b.show(); - - for (int npass = 0; npass < 2;) { - clock_t start = clock(); - visited_nodes = 0; - - SearchResult result = perfect(&b); - Move m = result.first; - - double sec = (double)(clock() - start) / CLOCKS_PER_SEC; - printf("time(%d): %d nodes / %.3f sec (%d nps)\n", - b.turn(), visited_nodes, sec, (int)(visited_nodes / sec)); - printf("\n%s (%d)\n", m.fourcc(), result.second); - - npass = m.is_pass() ? npass+1 : 0; - b.do_move(m); - b.show(); - } -} - -int main() -{ - wld_test(); - return 0; -} -#endif diff --git a/backend/search.h b/backend/search.h deleted file mode 100644 index c4e797a..0000000 --- a/backend/search.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SEARCH_H_ -#define SEARCH_H_ - -#include -typedef std::pair SearchResult; - -extern int visited_nodes; -extern bool quiet; - -class Timeout {}; - -SearchResult search_negascout(Board* node, int max_depth, - int stop_ms, int timeout_ms); -SearchResult wld(Board* node, int timeout_sec); -SearchResult perfect(Board* node); - -#endif // SEARCH_H_ diff --git a/backend/str.h b/backend/str.h deleted file mode 100644 index bb51305..0000000 --- a/backend/str.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef STR_H_ -#define STR_H_ - -//#define STR_ASCII - -#ifdef STR_ASCII - -#define STR_COLOR_SELECT "1:Human vs COM 2:COM vs Human 3:Human vs Human 4:COM vs COM [1-4] " -#define STR_VIOLET_BLOCK "#" -#define STR_ORANGE_BLOCK "&" -#define STR_BLANK " " -#define STR_EDGE "*" -#define STR_EFFECT "." -#define STR_BOARD_HEADER " 123456789ABCDE 123456789ABCDE" -#define STR_FRAME_TOP "+--------------+--------------+" -#define STR_FRAME_BOTTOM "+--------------+--------------+" -#define STR_FRAME_SIDE "|" - -#else // STR_ASCII - -#define STR_COLOR_SELECT "1:先手 2:後手 3:人間vs人間 4:COMvsCOM [1-4] " -#define STR_VIOLET_BLOCK "■" -#define STR_ORANGE_BLOCK "□" -#define STR_BLANK " " -#define STR_EDGE "☆" -#define STR_EFFECT "・" -#define STR_BOARD_HEADER " 1 2 3 4 5 6 7 8 9 A B C D E 1 2 3 4 5 6 7 8 9 A B C D E" -#define STR_FRAME_TOP "┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓" -#define STR_FRAME_BOTTOM "┗━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛" -#define STR_FRAME_SIDE "┃" - -#endif // STR_ASCII - -#endif // STR_H_ diff --git a/docs/hm5move.js b/docs/hm5move.js index 8e8b0a5..3ff6383 100644 --- a/docs/hm5move.js +++ b/docs/hm5move.js @@ -1 +1 @@ -var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=true;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}var wasmBinaryFile;wasmBinaryFile="hm5move.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinary(binaryFile))}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["g"];updateMemoryViews();wasmTable=Module["asm"]["k"];addOnInit(Module["asm"]["h"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function ___assert_fail(condition,filename,line,func){abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function _abort(){abort("")}function _emscripten_date_now(){return Date.now()}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}var printCharBuffers=[null,[],[]];function printChar(stream,curr){var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}}var SYSCALLS={varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret}};function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0}function getCFunc(ident){var func=Module["_"+ident];return func}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function stringToUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;itype==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return function(){return ccall(ident,returnType,argTypes,arguments,opts)}}var wasmImports={"f":___assert_fail,"b":___cxa_throw,"d":_abort,"a":_emscripten_date_now,"e":_emscripten_resize_heap,"c":_fd_write};var asm=createWasm();var ___wasm_call_ctors=function(){return(___wasm_call_ctors=Module["asm"]["h"]).apply(null,arguments)};var _hm5move=Module["_hm5move"]=function(){return(_hm5move=Module["_hm5move"]=Module["asm"]["i"]).apply(null,arguments)};var _getVisitedNodes=Module["_getVisitedNodes"]=function(){return(_getVisitedNodes=Module["_getVisitedNodes"]=Module["asm"]["j"]).apply(null,arguments)};var ___errno_location=function(){return(___errno_location=Module["asm"]["__errno_location"]).apply(null,arguments)};var stackSave=function(){return(stackSave=Module["asm"]["l"]).apply(null,arguments)};var stackRestore=function(){return(stackRestore=Module["asm"]["m"]).apply(null,arguments)};var stackAlloc=function(){return(stackAlloc=Module["asm"]["n"]).apply(null,arguments)};var ___cxa_is_pointer_type=function(){return(___cxa_is_pointer_type=Module["asm"]["o"]).apply(null,arguments)};Module["cwrap"]=cwrap;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();var hm5move=Module.cwrap("hm5move","string",["string","number"]);var getVisitedNodes=Module.cwrap("getVisitedNodes","number");function isValidPath(path){return path.search(/^((----|[1-9a-e]{2}[a-u][0-7])\/?)*$/)>=0}function depth(level){switch(level){case 2:return 10;case 3:return 10}return 3}function limit(level,player){var mult=[.9,1.1][player];switch(level){case 2:return 1e3*mult;case 3:return 1e4*mult}return 1e3*mult}function handle(data){var path=data.path;var level=data.level;if(isValidPath(path)){var start=Date.now();var player=path.split("/").length%2;var move=hm5move(path,depth(level),limit(level,player));var elapsed=(Date.now()-start)/1e3;postMessage({"move":move,"nps":getVisitedNodes()/elapsed})}else{postMessage({"move":"XXXX invalid path"})}}var ready=false;var onReady;addEventListener("message",function(e){if(ready)handle(e.data);else onReady=function(){handle(e.data)}});if(!Module["preRun"])Module["preRun"]=[];Module["preRun"].push(function(){ready=true;if(onReady)onReady()}); +var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=true;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var wasmBinaryFile;wasmBinaryFile="hm5move.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinarySync(binaryFile))}}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(instance=>instance).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["f"];updateMemoryViews();addOnInit(wasmExports["g"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var _abort=()=>{abort("")};var _emscripten_date_now=()=>Date.now();var _emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return function(){return ccall(ident,returnType,argTypes,arguments,opts)}};var wasmImports={b:___cxa_throw,c:_abort,a:_emscripten_date_now,e:_emscripten_memcpy_js,d:_emscripten_resize_heap};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["g"])();var _hm5move=Module["_hm5move"]=(a0,a1,a2)=>(_hm5move=Module["_hm5move"]=wasmExports["h"])(a0,a1,a2);var _getVisitedNodes=Module["_getVisitedNodes"]=()=>(_getVisitedNodes=Module["_getVisitedNodes"]=wasmExports["i"])();var ___errno_location=()=>(___errno_location=wasmExports["__errno_location"])();var stackSave=()=>(stackSave=wasmExports["k"])();var stackRestore=a0=>(stackRestore=wasmExports["l"])(a0);var stackAlloc=a0=>(stackAlloc=wasmExports["m"])(a0);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["n"])(a0);Module["cwrap"]=cwrap;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();var hm5move=Module.cwrap("hm5move","string",["string","number"]);var getVisitedNodes=Module.cwrap("getVisitedNodes","number");function isValidPath(path){return path.search(/^((----|[1-9a-e]{2}[a-u][0-7])\/?)*$/)>=0}function depth(level){switch(level){case 2:return 10;case 3:return 10}return 3}function limit(level,player){var mult=[.9,1.1][player];switch(level){case 2:return 1e3*mult;case 3:return 1e4*mult}return 1e3*mult}function handle(data){var path=data.path;var level=data.level;if(isValidPath(path)){var start=Date.now();var player=path.split("/").length%2;var move=hm5move(path,depth(level),limit(level,player));var elapsed=(Date.now()-start)/1e3;postMessage({"move":move,"nps":getVisitedNodes()/elapsed})}else{postMessage({"move":"XXXX invalid path"})}}var ready=false;var onReady;addEventListener("message",function(e){if(ready)handle(e.data);else onReady=function(){handle(e.data)}});if(!Module["preRun"])Module["preRun"]=[];Module["preRun"].push(function(){ready=true;if(onReady)onReady()}); diff --git a/docs/hm5move.wasm b/docs/hm5move.wasm index edd4830dc92807269c25f8a1dbe72820306bd468..926937026338be4ac261dfe54d4b60acb19d0f90 100755 GIT binary patch literal 80384 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

-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 YOV diff --git a/wasm/CMakeLists.txt b/wasm/CMakeLists.txt new file mode 100644 index 0000000..4c71c8c --- /dev/null +++ b/wasm/CMakeLists.txt @@ -0,0 +1,15 @@ +project(blokusduo-wasm) +cmake_minimum_required(VERSION 3.15...3.27) + +set(CMAKE_CXX_STANDARD 17) + +add_subdirectory(blokusduo) + +add_executable(hm5move hm5move.cpp) +target_link_libraries(hm5move blokusduo) + +target_link_options(hm5move PRIVATE + "SHELL:-s ENVIRONMENT=worker" + "SHELL:-s EXPORTED_FUNCTIONS=_hm5move,_getVisitedNodes" + "SHELL:-s EXPORTED_RUNTIME_METHODS=cwrap" + --post-js=${CMAKE_CURRENT_SOURCE_DIR}/hm5move_post.js) diff --git a/wasm/blokusduo b/wasm/blokusduo new file mode 160000 index 0000000..17365d8 --- /dev/null +++ b/wasm/blokusduo @@ -0,0 +1 @@ +Subproject commit 17365d8c5295c032455335f5e70de212ca1d427e diff --git a/wasm/hm5move.cpp b/wasm/hm5move.cpp new file mode 100644 index 0000000..e22b6e5 --- /dev/null +++ b/wasm/hm5move.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include "blokusduo.h" +using namespace blokusduo; + +extern "C" const char* hm5move(const char* pathstr, int max_depth, + int time_limit); +extern "C" int getVisitedNodes(); + +Move com_move(const Board& b, int max_depth, int time_ms) { + Move move; + int score = 100; + + move = search::opening_move(b); + if (move == Move::invalid()) { + search::SearchResult r; + if (b.turn() < 25) + r = search::negascout(b, max_depth, time_ms / 2, time_ms); + else if (b.turn() < 27) + r = search::wld(b, 1000); + else + r = search::perfect(b); + move = r.first; + score = r.second; + } + + return move; +} + +const char* hm5move(const char* path, int max_depth, int time_limit) { + static std::string fourcc; + static bool initialized = false; + if (!initialized) { + srand(time(nullptr)); + initialized = true; + } + + Board b; + while (*path) { + Move m(path); + path += 4; + if (*path == '/') path++; + if (m == Move::invalid() || !b.is_valid_move(m)) + return "XXXX invalid move "; + b.play_move(m); + } + search::visited_nodes = 0; + Move m = com_move(b, max_depth, time_limit); + fourcc = m.fourcc(); + return fourcc.c_str(); +} + +int getVisitedNodes() { return search::visited_nodes; } diff --git a/backend/hm5move_post.js b/wasm/hm5move_post.js similarity index 100% rename from backend/hm5move_post.js rename to wasm/hm5move_post.js