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 edd4830..9269370 100755 Binary files a/docs/hm5move.wasm and b/docs/hm5move.wasm differ 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