const int edges[107] = {
0, /* 1-based */
/* 1 */ 17,
/* 2 */ 16,
/* 3 */ 0,
/* 4 */ 1,
/* 5 */ 16,
/* 6 */ 0,
/* 7 */ 0,
/* 8 */ 0,
/* 9 */ 1,
/* 10 */ 16,
/* 11 */ 0,
/* 12 */ 0,
/* 13 */ 0,
/* 14 */ 0,
/* 15 */ 0,
/* 16 */ 1,
/* 17 */ 16,
/* 18 */ 0,
/* 19 */ 0,
/* 20 */ 0,
/* 21 */ 0,
/* 22 */ 0,
/* 23 */ 0,
/* 24 */ 0,
/* 25 */ 1,
/* 26 */ 16,
/* 27 */ 0,
/* 28 */ 0,
/* 29 */ 0,
/* 30 */ 0,
/* 31 */ 0,
/* 32 */ 0,
/* 33 */ 0,
/* 34 */ 0,
/* 35 */ 0,
/* 36 */ 1,
/* 37 */ 24,
/* 38 */ 0,
/* 39 */ 0,
/* 40 */ 0,
/* 41 */ 0,
/* 42 */ 0,
/* 43 */ 0,
/* 44 */ 0,
/* 45 */ 0,
/* 46 */ 0,
/* 47 */ 0,
/* 48 */ 0,
/* 49 */ 3,
/* 50 */ 8,
/* 51 */ 0,
/* 52 */ 0,
/* 53 */ 0,
/* 54 */ 0,
/* 55 */ 0,
/* 56 */ 0,
/* 57 */ 0,
/* 58 */ 0,
/* 59 */ 0,
/* 60 */ 0,
/* 61 */ 2,
/* 62 */ 8,
/* 63 */ 0,
/* 64 */ 0,
/* 65 */ 0,
/* 66 */ 0,
/* 67 */ 0,
/* 68 */ 0,
/* 69 */ 0,
/* 70 */ 0,
/* 71 */ 0,
/* 72 */ 2,
/* 73 */ 8,
/* 74 */ 0,
/* 75 */ 0,
/* 76 */ 0,
/* 77 */ 0,
/* 78 */ 0,
/* 79 */ 0,
/* 80 */ 0,
/* 81 */ 0,
/* 82 */ 2,
/* 83 */ 8,
/* 84 */ 0,
/* 85 */ 0,
/* 86 */ 0,
/* 87 */ 0,
/* 88 */ 0,
/* 89 */ 0,
/* 90 */ 0,
/* 91 */ 2,
/* 92 */ 8,
/* 93 */ 0,
/* 94 */ 0,
/* 95 */ 0,
/* 96 */ 0,
/* 97 */ 0,
/* 98 */ 0,
/* 99 */ 2,
/* 100 */ 12,
/* 101 */ 4,
/* 102 */ 4,
/* 103 */ 4,
/* 104 */ 4,
/* 105 */ 4,
/* 106 */ 6,
};
const int rowsize[] = {1, 3, 5, 7, 9, 11, 13, 12, 11, 10, 9, 8, 7, 0};
const int edge_cells[] = {1, 2, 4, 5, 9, 10, 16, 17, 25, 26, 36, 37, 49, 50, 61, 62, 72, 73, 82, 83, 91, 92, 99, 100, 101, 102, 103, 104, 105, 106, 0};
const int corner_cells[] = {1, 37, 49, 100, 106, 0};
const int neighs[107][6] = {
{}, /* 1-based */
/* 1 */ { 2, 3, 4},
/* 2 */ { 1, 3, 5, 6},
/* 3 */ { 1, 2, 4, 6, 7, 8},
/* 4 */ { 1, 3, 8, 9},
/* 5 */ { 2, 6, 10, 11},
/* 6 */ { 2, 3, 5, 7, 11, 12},
/* 7 */ { 3, 6, 8, 12, 13, 14},
/* 8 */ { 3, 4, 7, 9, 14, 15},
/* 9 */ { 4, 8, 15, 16},
/* 10 */ { 5, 11, 17, 18},
/* 11 */ { 5, 6, 10, 12, 18, 19},
/* 12 */ { 6, 7, 11, 13, 19, 20},
/* 13 */ { 7, 12, 14, 20, 21, 22},
/* 14 */ { 7, 8, 13, 15, 22, 23},
/* 15 */ { 8, 9, 14, 16, 23, 24},
/* 16 */ { 9, 15, 24, 25},
/* 17 */ { 10, 18, 26, 27},
/* 18 */ { 10, 11, 17, 19, 27, 28},
/* 19 */ { 11, 12, 18, 20, 28, 29},
/* 20 */ { 12, 13, 19, 21, 29, 30},
/* 21 */ { 13, 20, 22, 30, 31, 32},
/* 22 */ { 13, 14, 21, 23, 32, 33},
/* 23 */ { 14, 15, 22, 24, 33, 34},
/* 24 */ { 15, 16, 23, 25, 34, 35},
/* 25 */ { 16, 24, 35, 36},
/* 26 */ { 17, 27, 37, 38},
/* 27 */ { 17, 18, 26, 28, 38, 39},
/* 28 */ { 18, 19, 27, 29, 39, 40},
/* 29 */ { 19, 20, 28, 30, 40, 41},
/* 30 */ { 20, 21, 29, 31, 41, 42},
/* 31 */ { 21, 30, 32, 42, 43, 44},
/* 32 */ { 21, 22, 31, 33, 44, 45},
/* 33 */ { 22, 23, 32, 34, 45, 46},
/* 34 */ { 23, 24, 33, 35, 46, 47},
/* 35 */ { 24, 25, 34, 36, 47, 48},
/* 36 */ { 25, 35, 48, 49},
/* 37 */ { 26, 38, 50},
/* 38 */ { 26, 27, 37, 39, 50, 51},
/* 39 */ { 27, 28, 38, 40, 51, 52},
/* 40 */ { 28, 29, 39, 41, 52, 53},
/* 41 */ { 29, 30, 40, 42, 53, 54},
/* 42 */ { 30, 31, 41, 43, 54, 55},
/* 43 */ { 31, 42, 44, 55, 56},
/* 44 */ { 31, 32, 43, 45, 56, 57},
/* 45 */ { 32, 33, 44, 46, 57, 58},
/* 46 */ { 33, 34, 45, 47, 58, 59},
/* 47 */ { 34, 35, 46, 48, 59, 60},
/* 48 */ { 35, 36, 47, 49, 60, 61},
/* 49 */ { 36, 48, 61},
/* 50 */ { 37, 38, 51, 62},
/* 51 */ { 38, 39, 50, 52, 62, 63},
/* 52 */ { 39, 40, 51, 53, 63, 64},
/* 53 */ { 40, 41, 52, 54, 64, 65},
/* 54 */ { 41, 42, 53, 55, 65, 66},
/* 55 */ { 42, 43, 54, 56, 66, 67},
/* 56 */ { 43, 44, 55, 57, 67, 68},
/* 57 */ { 44, 45, 56, 58, 68, 69},
/* 58 */ { 45, 46, 57, 59, 69, 70},
/* 59 */ { 46, 47, 58, 60, 70, 71},
/* 60 */ { 47, 48, 59, 61, 71, 72},
/* 61 */ { 48, 49, 60, 72},
/* 62 */ { 50, 51, 63, 73},
/* 63 */ { 51, 52, 62, 64, 73, 74},
/* 64 */ { 52, 53, 63, 65, 74, 75},
/* 65 */ { 53, 54, 64, 66, 75, 76},
/* 66 */ { 54, 55, 65, 67, 76, 77},
/* 67 */ { 55, 56, 66, 68, 77, 78},
/* 68 */ { 56, 57, 67, 69, 78, 79},
/* 69 */ { 57, 58, 68, 70, 79, 80},
/* 70 */ { 58, 59, 69, 71, 80, 81},
/* 71 */ { 59, 60, 70, 72, 81, 82},
/* 72 */ { 60, 61, 71, 82},
/* 73 */ { 62, 63, 74, 83},
/* 74 */ { 63, 64, 73, 75, 83, 84},
/* 75 */ { 64, 65, 74, 76, 84, 85},
/* 76 */ { 65, 66, 75, 77, 85, 86},
/* 77 */ { 66, 67, 76, 78, 86, 87},
/* 78 */ { 67, 68, 77, 79, 87, 88},
/* 79 */ { 68, 69, 78, 80, 88, 89},
/* 80 */ { 69, 70, 79, 81, 89, 90},
/* 81 */ { 70, 71, 80, 82, 90, 91},
/* 82 */ { 71, 72, 81, 91},
/* 83 */ { 73, 74, 84, 92},
/* 84 */ { 74, 75, 83, 85, 92, 93},
/* 85 */ { 75, 76, 84, 86, 93, 94},
/* 86 */ { 76, 77, 85, 87, 94, 95},
/* 87 */ { 77, 78, 86, 88, 95, 96},
/* 88 */ { 78, 79, 87, 89, 96, 97},
/* 89 */ { 79, 80, 88, 90, 97, 98},
/* 90 */ { 80, 81, 89, 91, 98, 99},
/* 91 */ { 81, 82, 90, 99},
/* 92 */ { 83, 84, 93,100},
/* 93 */ { 84, 85, 92, 94,100,101},
/* 94 */ { 85, 86, 93, 95,101,102},
/* 95 */ { 86, 87, 94, 96,102,103},
/* 96 */ { 87, 88, 95, 97,103,104},
/* 97 */ { 88, 89, 96, 98,104,105},
/* 98 */ { 89, 90, 97, 99,105,106},
/* 99 */ { 90, 91, 98,106},
/* 100 */ { 92, 93,101},
/* 101 */ { 93, 94,100,102},
/* 102 */ { 94, 95,101,103},
/* 103 */ { 95, 96,102,104},
/* 104 */ { 96, 97,103,105},
/* 105 */ { 97, 98,104,106},
/* 106 */ { 98, 99,105},
};
const int common_neighs[107][6][3] = {
{}, /* 1-based */
/* 1 */ {{ 6, 2, 3}, { 8, 3, 4}},
/* 2 */ {{ 4, 1, 3}, { 7, 3, 6}, { 11, 5, 6}},
/* 3 */ {{ 5, 2, 6}, { 9, 8, 4}, { 12, 6, 7}, { 14, 8, 7}},
/* 4 */ {{ 2, 1, 3}, { 7, 8, 3}, { 15, 8, 9}},
/* 5 */ {{ 3, 2, 6}, { 12, 11, 6}, { 18, 10, 11}},
/* 6 */ {{ 1, 2, 3}, { 8, 3, 7}, { 10, 11, 5}, { 13, 12, 7}, { 19, 11, 12}},
/* 7 */ {{ 2, 3, 6}, { 4, 8, 3}, { 11, 12, 6}, { 15, 8, 14}, { 20, 12, 13}, { 22, 13, 14}},
/* 8 */ {{ 1, 3, 4}, { 6, 3, 7}, { 13, 14, 7}, { 16, 9, 15}, { 23, 14, 15}},
/* 9 */ {{ 3, 8, 4}, { 14, 8, 15}, { 24, 16, 15}},
/* 10 */ {{ 6, 11, 5}, { 19, 18, 11}, { 27, 17, 18}},
/* 11 */ {{ 2, 5, 6}, { 7, 12, 6}, { 17, 18, 10}, { 20, 19, 12}, { 28, 18, 19}},
/* 12 */ {{ 3, 6, 7}, { 5, 11, 6}, { 14, 13, 7}, { 18, 19, 11}, { 21, 20, 13}, { 29, 19, 20}},
/* 13 */ {{ 6, 12, 7}, { 8, 14, 7}, { 19, 20, 12}, { 23, 22, 14}, { 30, 20, 21}, { 32, 21, 22}},
/* 14 */ {{ 3, 8, 7}, { 9, 8, 15}, { 12, 13, 7}, { 21, 13, 22}, { 24, 23, 15}, { 33, 22, 23}},
/* 15 */ {{ 4, 8, 9}, { 7, 8, 14}, { 22, 14, 23}, { 25, 24, 16}, { 34, 24, 23}},
/* 16 */ {{ 8, 9, 15}, { 23, 24, 15}, { 35, 24, 25}},
/* 17 */ {{ 11, 18, 10}, { 28, 18, 27}, { 38, 26, 27}},
/* 18 */ {{ 5, 10, 11}, { 12, 19, 11}, { 26, 17, 27}, { 29, 19, 28}, { 39, 27, 28}},
/* 19 */ {{ 6, 11, 12}, { 10, 18, 11}, { 13, 20, 12}, { 27, 18, 28}, { 30, 20, 29}, { 40, 28, 29}},
/* 20 */ {{ 7, 12, 13}, { 11, 19, 12}, { 22, 13, 21}, { 28, 19, 29}, { 31, 21, 30}, { 41, 29, 30}},
/* 21 */ {{ 12, 20, 13}, { 14, 13, 22}, { 29, 20, 30}, { 33, 32, 22}, { 42, 30, 31}, { 44, 32, 31}},
/* 22 */ {{ 7, 13, 14}, { 15, 14, 23}, { 20, 13, 21}, { 31, 32, 21}, { 34, 33, 23}, { 45, 32, 33}},
/* 23 */ {{ 8, 14, 15}, { 13, 22, 14}, { 16, 24, 15}, { 32, 33, 22}, { 35, 24, 34}, { 46, 33, 34}},
/* 24 */ {{ 9, 16, 15}, { 14, 23, 15}, { 33, 34, 23}, { 36, 25, 35}, { 47, 34, 35}},
/* 25 */ {{ 15, 24, 16}, { 34, 24, 35}, { 48, 35, 36}},
/* 26 */ {{ 18, 17, 27}, { 39, 27, 38}, { 50, 37, 38}},
/* 27 */ {{ 10, 17, 18}, { 19, 18, 28}, { 37, 26, 38}, { 40, 28, 39}, { 51, 38, 39}},
/* 28 */ {{ 11, 18, 19}, { 17, 18, 27}, { 20, 19, 29}, { 38, 27, 39}, { 41, 40, 29}, { 52, 40, 39}},
/* 29 */ {{ 12, 19, 20}, { 18, 19, 28}, { 21, 20, 30}, { 39, 40, 28}, { 42, 41, 30}, { 53, 40, 41}},
/* 30 */ {{ 13, 20, 21}, { 19, 20, 29}, { 32, 21, 31}, { 40, 41, 29}, { 43, 42, 31}, { 54, 41, 42}},
/* 31 */ {{ 20, 21, 30}, { 22, 32, 21}, { 41, 42, 30}, { 45, 32, 44}, { 55, 42, 43}, { 56, 43, 44}},
/* 32 */ {{ 13, 21, 22}, { 23, 33, 22}, { 30, 21, 31}, { 43, 44, 31}, { 46, 33, 45}, { 57, 44, 45}},
/* 33 */ {{ 14, 22, 23}, { 21, 32, 22}, { 24, 34, 23}, { 44, 32, 45}, { 47, 34, 46}, { 58, 45, 46}},
/* 34 */ {{ 15, 24, 23}, { 22, 33, 23}, { 25, 24, 35}, { 45, 33, 46}, { 48, 35, 47}, { 59, 46, 47}},
/* 35 */ {{ 16, 24, 25}, { 23, 24, 34}, { 46, 34, 47}, { 49, 48, 36}, { 60, 48, 47}},
/* 36 */ {{ 24, 25, 35}, { 47, 48, 35}, { 61, 48, 49}},
/* 37 */ {{ 27, 26, 38}, { 51, 50, 38}},
/* 38 */ {{ 17, 26, 27}, { 28, 27, 39}, { 52, 51, 39}, { 62, 50, 51}},
/* 39 */ {{ 18, 27, 28}, { 26, 27, 38}, { 29, 40, 28}, { 50, 51, 38}, { 53, 40, 52}, { 63, 51, 52}},
/* 40 */ {{ 19, 28, 29}, { 27, 28, 39}, { 30, 41, 29}, { 51, 52, 39}, { 54, 41, 53}, { 64, 52, 53}},
/* 41 */ {{ 20, 29, 30}, { 28, 40, 29}, { 31, 42, 30}, { 52, 40, 53}, { 55, 42, 54}, { 65, 53, 54}},
/* 42 */ {{ 21, 30, 31}, { 29, 41, 30}, { 44, 43, 31}, { 53, 41, 54}, { 56, 43, 55}, { 66, 54, 55}},
/* 43 */ {{ 30, 42, 31}, { 32, 44, 31}, { 54, 42, 55}, { 57, 56, 44}, { 67, 56, 55}},
/* 44 */ {{ 21, 32, 31}, { 33, 32, 45}, { 42, 43, 31}, { 55, 56, 43}, { 58, 57, 45}, { 68, 56, 57}},
/* 45 */ {{ 22, 32, 33}, { 31, 32, 44}, { 34, 33, 46}, { 56, 57, 44}, { 59, 58, 46}, { 69, 57, 58}},
/* 46 */ {{ 23, 33, 34}, { 32, 33, 45}, { 35, 34, 47}, { 57, 58, 45}, { 60, 59, 47}, { 70, 58, 59}},
/* 47 */ {{ 24, 34, 35}, { 33, 34, 46}, { 36, 48, 35}, { 58, 59, 46}, { 61, 48, 60}, { 71, 59, 60}},
/* 48 */ {{ 25, 35, 36}, { 34, 35, 47}, { 59, 60, 47}, { 72, 60, 61}},
/* 49 */ {{ 35, 48, 36}, { 60, 48, 61}},
/* 50 */ {{ 26, 37, 38}, { 39, 51, 38}, { 63, 51, 62}},
/* 51 */ {{ 27, 38, 39}, { 37, 50, 38}, { 40, 52, 39}, { 64, 52, 63}, { 73, 62, 63}},
/* 52 */ {{ 28, 40, 39}, { 38, 51, 39}, { 41, 40, 53}, { 62, 51, 63}, { 65, 64, 53}, { 74, 64, 63}},
/* 53 */ {{ 29, 40, 41}, { 39, 40, 52}, { 42, 41, 54}, { 63, 64, 52}, { 66, 65, 54}, { 75, 64, 65}},
/* 54 */ {{ 30, 41, 42}, { 40, 41, 53}, { 43, 42, 55}, { 64, 65, 53}, { 67, 66, 55}, { 76, 65, 66}},
/* 55 */ {{ 31, 42, 43}, { 41, 42, 54}, { 44, 56, 43}, { 65, 66, 54}, { 68, 56, 67}, { 77, 66, 67}},
/* 56 */ {{ 31, 43, 44}, { 42, 43, 55}, { 45, 57, 44}, { 66, 67, 55}, { 69, 57, 68}, { 78, 67, 68}},
/* 57 */ {{ 32, 44, 45}, { 43, 56, 44}, { 46, 58, 45}, { 67, 56, 68}, { 70, 58, 69}, { 79, 68, 69}},
/* 58 */ {{ 33, 45, 46}, { 44, 57, 45}, { 47, 59, 46}, { 68, 57, 69}, { 71, 59, 70}, { 80, 69, 70}},
/* 59 */ {{ 34, 46, 47}, { 45, 58, 46}, { 48, 60, 47}, { 69, 58, 70}, { 72, 60, 71}, { 81, 70, 71}},
/* 60 */ {{ 35, 48, 47}, { 46, 59, 47}, { 49, 48, 61}, { 70, 59, 71}, { 82, 72, 71}},
/* 61 */ {{ 36, 48, 49}, { 47, 48, 60}, { 71, 72, 60}},
/* 62 */ {{ 38, 50, 51}, { 52, 51, 63}, { 74, 73, 63}},
/* 63 */ {{ 39, 51, 52}, { 50, 51, 62}, { 53, 64, 52}, { 75, 64, 74}, { 83, 73, 74}},
/* 64 */ {{ 40, 52, 53}, { 51, 52, 63}, { 54, 65, 53}, { 73, 74, 63}, { 76, 65, 75}, { 84, 74, 75}},
/* 65 */ {{ 41, 53, 54}, { 52, 64, 53}, { 55, 66, 54}, { 74, 64, 75}, { 77, 66, 76}, { 85, 75, 76}},
/* 66 */ {{ 42, 54, 55}, { 53, 65, 54}, { 56, 67, 55}, { 75, 65, 76}, { 78, 67, 77}, { 86, 76, 77}},
/* 67 */ {{ 43, 56, 55}, { 54, 66, 55}, { 57, 56, 68}, { 76, 66, 77}, { 79, 68, 78}, { 87, 77, 78}},
/* 68 */ {{ 44, 56, 57}, { 55, 56, 67}, { 58, 57, 69}, { 77, 67, 78}, { 80, 69, 79}, { 88, 78, 79}},
/* 69 */ {{ 45, 57, 58}, { 56, 57, 68}, { 59, 58, 70}, { 78, 68, 79}, { 81, 80, 70}, { 89, 80, 79}},
/* 70 */ {{ 46, 58, 59}, { 57, 58, 69}, { 60, 59, 71}, { 79, 80, 69}, { 82, 81, 71}, { 90, 80, 81}},
/* 71 */ {{ 47, 59, 60}, { 58, 59, 70}, { 61, 72, 60}, { 80, 81, 70}, { 91, 81, 82}},
/* 72 */ {{ 48, 60, 61}, { 59, 60, 71}, { 81, 82, 71}},
/* 73 */ {{ 51, 62, 63}, { 64, 74, 63}, { 84, 74, 83}},
/* 74 */ {{ 52, 64, 63}, { 62, 73, 63}, { 65, 64, 75}, { 85, 75, 84}, { 92, 83, 84}},
/* 75 */ {{ 53, 64, 65}, { 63, 64, 74}, { 66, 65, 76}, { 83, 74, 84}, { 86, 76, 85}, { 93, 84, 85}},
/* 76 */ {{ 54, 65, 66}, { 64, 65, 75}, { 67, 66, 77}, { 84, 75, 85}, { 87, 77, 86}, { 94, 85, 86}},
/* 77 */ {{ 55, 66, 67}, { 65, 66, 76}, { 68, 67, 78}, { 85, 76, 86}, { 88, 78, 87}, { 95, 86, 87}},
/* 78 */ {{ 56, 67, 68}, { 66, 67, 77}, { 69, 68, 79}, { 86, 77, 87}, { 89, 88, 79}, { 96, 88, 87}},
/* 79 */ {{ 57, 68, 69}, { 67, 68, 78}, { 70, 80, 69}, { 87, 88, 78}, { 90, 80, 89}, { 97, 88, 89}},
/* 80 */ {{ 58, 69, 70}, { 68, 69, 79}, { 71, 81, 70}, { 88, 89, 79}, { 91, 81, 90}, { 98, 89, 90}},
/* 81 */ {{ 59, 70, 71}, { 69, 80, 70}, { 72, 82, 71}, { 89, 80, 90}, { 99, 90, 91}},
/* 82 */ {{ 60, 72, 71}, { 70, 81, 71}, { 90, 81, 91}},
/* 83 */ {{ 63, 73, 74}, { 75, 74, 84}, { 93, 84, 92}},
/* 84 */ {{ 64, 74, 75}, { 73, 74, 83}, { 76, 75, 85}, { 94, 85, 93}, {100, 92, 93}},
/* 85 */ {{ 65, 75, 76}, { 74, 75, 84}, { 77, 76, 86}, { 92, 84, 93}, { 95, 94, 86}, {101, 93, 94}},
/* 86 */ {{ 66, 76, 77}, { 75, 76, 85}, { 78, 77, 87}, { 93, 85, 94}, { 96, 95, 87}, {102, 94, 95}},
/* 87 */ {{ 67, 77, 78}, { 76, 77, 86}, { 79, 88, 78}, { 94, 86, 95}, { 97, 96, 88}, {103, 96, 95}},
/* 88 */ {{ 68, 78, 79}, { 77, 78, 87}, { 80, 89, 79}, { 95, 96, 87}, { 98, 97, 89}, {104, 96, 97}},
/* 89 */ {{ 69, 80, 79}, { 78, 88, 79}, { 81, 80, 90}, { 96, 88, 97}, { 99, 98, 90}, {105, 97, 98}},
/* 90 */ {{ 70, 80, 81}, { 79, 80, 89}, { 82, 81, 91}, { 97, 89, 98}, {106, 98, 99}},
/* 91 */ {{ 71, 81, 82}, { 80, 81, 90}, { 98, 90, 99}},
/* 92 */ {{ 74, 83, 84}, { 85, 84, 93}, {101,100, 93}},
/* 93 */ {{ 75, 84, 85}, { 83, 84, 92}, { 86, 85, 94}, {102,101, 94}},
/* 94 */ {{ 76, 85, 86}, { 84, 85, 93}, { 87, 86, 95}, {100,101, 93}, {103,102, 95}},
/* 95 */ {{ 77, 86, 87}, { 85, 94, 86}, { 88, 96, 87}, {101,102, 94}, {104, 96,103}},
/* 96 */ {{ 78, 88, 87}, { 86, 95, 87}, { 89, 88, 97}, {102,103, 95}, {105,104, 97}},
/* 97 */ {{ 79, 88, 89}, { 87, 96, 88}, { 90, 89, 98}, {103,104, 96}, {106,105, 98}},
/* 98 */ {{ 80, 89, 90}, { 88, 97, 89}, { 91, 90, 99}, {104,105, 97}},
/* 99 */ {{ 81, 90, 91}, { 89, 98, 90}, {105,106, 98}},
/* 100 */ {{ 84, 92, 93}, { 94,101, 93}},
/* 101 */ {{ 85, 93, 94}, { 92,100, 93}, { 95,102, 94}},
/* 102 */ {{ 86, 94, 95}, { 93,101, 94}, { 96,103, 95}},
/* 103 */ {{ 87, 96, 95}, { 94,102, 95}, { 97,104, 96}},
/* 104 */ {{ 88, 96, 97}, { 95, 96,103}, { 98,105, 97}},
/* 105 */ {{ 89, 97, 98}, { 96,104, 97}, { 99,106, 98}},
/* 106 */ {{ 90, 98, 99}, { 97,105, 98}},
};
const int edge_neighs[107][3] = {
{}, /* 1-based */
/* 1 */ {},
/* 2 */ {},
/* 3 */ { 1, 2, 4},
/* 4 */ {},
/* 5 */ {},
/* 6 */ { 2, 5},
/* 7 */ {},
/* 8 */ { 4, 9},
/* 9 */ {},
/* 10 */ {},
/* 11 */ { 5, 10},
/* 12 */ {},
/* 13 */ {},
/* 14 */ {},
/* 15 */ { 9, 16},
/* 16 */ {},
/* 17 */ {},
/* 18 */ { 10, 17},
/* 19 */ {},
/* 20 */ {},
/* 21 */ {},
/* 22 */ {},
/* 23 */ {},
/* 24 */ { 16, 25},
/* 25 */ {},
/* 26 */ {},
/* 27 */ { 17, 26},
/* 28 */ {},
/* 29 */ {},
/* 30 */ {},
/* 31 */ {},
/* 32 */ {},
/* 33 */ {},
/* 34 */ {},
/* 35 */ { 36, 25},
/* 36 */ {},
/* 37 */ {},
/* 38 */ { 37, 50, 26},
/* 39 */ {},
/* 40 */ {},
/* 41 */ {},
/* 42 */ {},
/* 43 */ {},
/* 44 */ {},
/* 45 */ {},
/* 46 */ {},
/* 47 */ {},
/* 48 */ { 36, 49, 61},
/* 49 */ {},
/* 50 */ {},
/* 51 */ { 50, 62},
/* 52 */ {},
/* 53 */ {},
/* 54 */ {},
/* 55 */ {},
/* 56 */ {},
/* 57 */ {},
/* 58 */ {},
/* 59 */ {},
/* 60 */ { 72, 61},
/* 61 */ {},
/* 62 */ {},
/* 63 */ { 73, 62},
/* 64 */ {},
/* 65 */ {},
/* 66 */ {},
/* 67 */ {},
/* 68 */ {},
/* 69 */ {},
/* 70 */ {},
/* 71 */ { 72, 82},
/* 72 */ {},
/* 73 */ {},
/* 74 */ { 73, 83},
/* 75 */ {},
/* 76 */ {},
/* 77 */ {},
/* 78 */ {},
/* 79 */ {},
/* 80 */ {},
/* 81 */ { 82, 91},
/* 82 */ {},
/* 83 */ {},
/* 84 */ { 83, 92},
/* 85 */ {},
/* 86 */ {},
/* 87 */ {},
/* 88 */ {},
/* 89 */ {},
/* 90 */ { 99, 91},
/* 91 */ {},
/* 92 */ {},
/* 93 */ {100,101, 92},
/* 94 */ {101,102},
/* 95 */ {102,103},
/* 96 */ {103,104},
/* 97 */ {104,105},
/* 98 */ { 99,105,106},
/* 99 */ {},
/* 100 */ {},
/* 101 */ {},
/* 102 */ {},
/* 103 */ {},
/* 104 */ {},
/* 105 */ {},
/* 106 */ {},
};
const int edge2corner[] = {
/* 0 */ 0, /* 0 -> 0 */
/* 1 */ 0, /* TOPRIGHT -> 0 */
/* 2 */ 0, /* BOTTOMRIGHT -> 0 */
/* 3 */ 0, /* TOPRIGHT|BOTTOMRIGHT -> 0 */
/* 4 */ 0, /* BOTTOM -> 0 */
/* 5 */ 0, /* TOPRIGHT|BOTTOM -> 0 */
/* 6 */ 0, /* BOTTOMRIGHT|BOTTOM -> 0 */
/* 7 */ 6, /* TOPRIGHT|BOTTOMRIGHT|BOTTOM -> MIDRIGHT|BOTTOMRIGHT */
/* 8 */ 0, /* BOTTOMLEFT -> 0 */
/* 9 */ 0, /* TOPRIGHT|BOTTOMLEFT -> 0 */
/* 10 */ 0, /* BOTTOMRIGHT|BOTTOMLEFT -> 0 */
/* 11 */ 2, /* TOPRIGHT|BOTTOMRIGHT|BOTTOMLEFT -> MIDRIGHT */
/* 12 */ 0, /* BOTTOM|BOTTOMLEFT -> 0 */
/* 13 */ 8, /* TOPRIGHT|BOTTOM|BOTTOMLEFT -> BOTTOMLEFT */
/* 14 */ 12, /* BOTTOMRIGHT|BOTTOM|BOTTOMLEFT -> BOTTOMRIGHT|BOTTOMLEFT */
/* 15 */ 14, /* TOPRIGHT|BOTTOMRIGHT|BOTTOM|BOTTOMLEFT -> MIDRIGHT|BOTTOMRIGHT|BOTTOMLEFT */
/* 16 */ 0, /* TOPLEFT -> 0 */
/* 17 */ 0, /* TOPRIGHT|TOPLEFT -> 0 */
/* 18 */ 0, /* BOTTOMRIGHT|TOPLEFT -> 0 */
/* 19 */ 3, /* TOPRIGHT|BOTTOMRIGHT|TOPLEFT -> TOP|MIDRIGHT */
/* 20 */ 0, /* BOTTOM|TOPLEFT -> 0 */
/* 21 */ 1, /* TOPRIGHT|BOTTOM|TOPLEFT -> TOP */
/* 22 */ 4, /* BOTTOMRIGHT|BOTTOM|TOPLEFT -> BOTTOMRIGHT */
/* 23 */ 7, /* TOPRIGHT|BOTTOMRIGHT|BOTTOM|TOPLEFT -> TOP|MIDRIGHT|BOTTOMRIGHT */
/* 24 */ 0, /* BOTTOMLEFT|TOPLEFT -> 0 */
/* 25 */ 17, /* TOPRIGHT|BOTTOMLEFT|TOPLEFT -> TOP|MIDLEFT */
/* 26 */ 16, /* BOTTOMRIGHT|BOTTOMLEFT|TOPLEFT -> MIDLEFT */
/* 27 */ 19, /* TOPRIGHT|BOTTOMRIGHT|BOTTOMLEFT|TOPLEFT -> TOP|MIDRIGHT|MIDLEFT */
/* 28 */ 24, /* BOTTOM|BOTTOMLEFT|TOPLEFT -> BOTTOMLEFT|MIDLEFT */
/* 29 */ 25, /* TOPRIGHT|BOTTOM|BOTTOMLEFT|TOPLEFT -> TOP|BOTTOMLEFT|MIDLEFT */
/* 30 */ 28, /* BOTTOMRIGHT|BOTTOM|BOTTOMLEFT|TOPLEFT -> BOTTOMRIGHT|BOTTOMLEFT|MIDLEFT */
/* 31 */ 31, /* TOPRIGHT|BOTTOMRIGHT|BOTTOM|BOTTOMLEFT|TOPLEFT -> TOP|MIDRIGHT|BOTTOMRIGHT|BOTTOMLEFT|MIDLEFT */
};
const int bits[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5};
#define enough_corners(i) (0xfee8e880 & (1 << (i)))
#define E_TOPRIGHT 1
#define E_BOTTOMRIGHT 2
#define E_BOTTOM 4
#define E_BOTTOMLEFT 8
#define E_TOPLEFT 16
#define C_TOP 1
#define C_MIDRIGHT 2
#define C_BOTTOMRIGHT 4
#define C_BOTTOMLEFT 8
#define C_MIDLEFT 16
/* Apologies for my "French". :> */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <time.h>
#define MAX_DEPTH_START 3
int max_depth = MAX_DEPTH_START;
int verbose = 0;
#define EDGE_BITS 24
int first_moves[][40] = {{43, 0}, {55, 44, 0}, {43, 55, 44, 0}, {42, 44, 0}, {42, 43, 44, 0}, {31, 56, 0}, {31, 43, 56, 0}, {0}};
//int first_moves[][40] = {{37, 51, 64, 76, 87, 97, 106, 0}, {0}};
int start_paths[][2] = {{93, 48}, {38, 48}, {3, 98}, {3, 93}, {0}, /* END */ {85, 47}, {7, 89}, {39, 47}, {39, 89}, {0}};
int *first_move, *start_path;
void log_options(char *tag)
{
/*
FILE *fp = fopen("../options.log", "a");
fprintf(fp, "first_move %d %d %d %d start_path %d %d %s\n", first_move[0], first_move[1], first_move[2], first_move[3], start_path[0], start_path[1], tag ? tag : "");
fclose(fp);
*/
}
void pick_options()
{
int i;
for (i = 0; first_moves[i][0]; ++i)
if (random() < (RAND_MAX / (i + 1)))
first_move = first_moves[i];
for (i = 0; start_paths[i][0]; ++i)
if (random() < (RAND_MAX / (i + 1)))
start_path = start_paths[i];
log_options(NULL);
}
#define LOG(log...) fprintf(stderr, log)
typedef enum {
ST_1LINE = 0,
ST_HALFLINE,
ST_HALFLINE_DONE,
ST_EXTRALINE,
ST_FILLIN,
ST_FAILED,
} stage_t;
struct plans {
int todo[107];
int todolen;
stage_t stage;
};
struct game {
/* Bits 0 and 1 are player white and black.
Bits EDGE_BITS+ are edges touched indirectly by this field. */
int b[107];
/* 1-based arrray, bitfields showing which corners are owned by
each player. enough_corners() tells whether a player has won. */
int player_corners[3];
int turn;
int cur, me;
struct plans *plans;
};
struct game *new_game(void)
{
struct game
*g
= calloc(sizeof(struct game
), 1);
int i;
memset(g
, 0, sizeof(struct game
));
g->cur = g->turn = 1;
g->b[0] = -1;
for (i = 1; i <= 106; ++i)
g->b[i] = edges[i] << EDGE_BITS;
g
->plans
= calloc(sizeof(struct plans
), 1);
return g;
}
void print_board(struct game *g)
{
int i, j, nl;
const int *rs = rowsize;
if (!verbose)
return;
nl = 0;
for (i = 1; i < 107; ++i) {
if (nl == 0) {
LOG("%3d ", i);
for (j = 0; j < (13 - *rs); j++)
LOG(" ");
nl = *(rs++);
}
LOG("%2d", g->b[i] & 3);
if (--nl == 0)
LOG("\n");
}
}
void print_raw(int board[107])
{
int i, j, nl;
const int *rs = rowsize;
if (!verbose)
return;
nl = 0;
for (i = 1; i < 107; ++i) {
if (nl == 0) {
LOG("%3d ", i);
for (j = 0; j < (13 - *rs); j++)
LOG(" ");
nl = *(rs++);
}
LOG("%4d", board[i] & 0xffff);
if (--nl == 0)
LOG("\n");
}
}
int find_path_count_steps(struct game *g, int src, int dst,
int result[107], int step, int map[107])
{
int i, n, best = 9999;
/* Getting to a cell we already own is free, if it's empty it counts as a step/turn. */
if (!(g->b[src] & 3))
++step;
else if (!(g->b[src] & g->cur))
return best;
/* If we got here before with same/less effort, abort. */
if (step >= map[src])
return best;
/* Found a new best route to this point. */
map[src] = step;
/* Are we at our destination yet? */
if (src == dst) {
/* Found a new best route if we got this far. */
if (!(g->b[src] & 3))
result[step-1] = src;
return step;
}
for (i = 0; i < 6 && (n = neighs[src][i]); ++i) {
if (!(g->b[n] & (3 ^ g->cur))) {
int ret = find_path_count_steps(g, n, dst, result, step, map);
if (ret < best) {
best = ret;
result[step-1] = src;
}
}
}
return best;
}
int find_path(struct game *g, int src, int dst, int result[107])
{
int map[107] = {};
int fuck[108];
int ret = 0;
memset(map
, 0x7f, sizeof(map
));
/* TODO(wilmer): REmove the very very bad things done up here ([-1]) */
ret = find_path_count_steps(g, src, dst, fuck + 1, 0, map);
memcpy(result
, fuck
+ 1, sizeof(int) * 107);
//ret = find_path_count_steps(g, src, dst, result, 0, map);
/*
LOG("find_path(%d, %d) =", src, dst);
int i;
if (ret>100)
LOG(" %d", ret);
else
for (i = 0; i < ret; ++i)
LOG(" %d", result[i]);
LOG("\n");
*/
return ret < 999 ? ret : 1000000;
}
int find_path_triple(struct game *g, int a, int b, int c, int result[107])
{
int abbc[107], acbc[107];
struct game g2[1];
int ret = 0, best = 1000000;
int bc;
int i;
//LOG("Finding path for %d|%d|%d\n", a, b, c);
ret = find_path(g, a, b, abbc);
if (ret >= 999)
return best;
memcpy(g2
, g
, sizeof(struct game
));
for (i = 0; i < ret; ++i)
g2->b[abbc[i]] |= g2->cur;
bc = find_path(g2, b, c, abbc + ret);
if (bc >= 999)
return best;
best = ret + bc;
/* No need to try abac, since find_path() will already try that out. */
ret = find_path(g, a, c, acbc);
/* ab and bc are reachable, so is ac, no need to check. */
memcpy(g2
, g
, sizeof(struct game
));
for (i = 0; i < ret; ++i)
g2->b[acbc[i]] |= g2->cur;
ret += find_path(g2, b, c, acbc + ret);
if (ret < best) {
memcpy(result
, acbc
, sizeof(int) * ret
);
best = ret;
} else {
memcpy(result
, abbc
, sizeof(int) * best
);
}
/*
LOG("find_path_triple =>");
for (i = 0; i < best; ++i)
LOG(" %d", result[i]);
LOG("\n");
*/
return best;
}
void find_safe_paths_int(struct game *g, int src, int poss[107], int depth)
{
int i, n;
if ((g->b[src] & (g->cur ^ 3)) || (poss[src] & 0x1000000))
return;
++poss[src];
if (depth == 1) /* 1-based so initial depth == number of moves */
return;
poss[src] |= 0x1000000; /* Mark as seen, avoid cycles. */
for (i = 0; i < 6 && (n = common_neighs[src][i][0]); ++i) {
/* Opponent is (partially) on the way, this destination is unsafe. */
if ((g->b[common_neighs[src][i][1]] | g->b[common_neighs[src][i][2]]) & (g->cur ^ 3))
continue;
find_safe_paths_int(g, n, poss, depth - 1);
}
poss[src] &= ~0x1000000;
}
void find_safe_path_int(struct game *g, int src, int dst, int result[107], int work[107], int depth)
{
int i, n;
if ((g->b[src] & (g->cur ^ 3)) || (work[src] & 0x1000000))
return;
if (depth == 1) /* 1-based so initial depth == number of moves */
return;
if (!(g->b[src] & g->cur))
work[src] += 1000;
work[src] |= 0x1000000; /* Mark as seen, avoid cycles. */
if (src == dst) {
n = 0;
/* Fragile: Count number of moves left to do. Mandatory counts
as 1, optional only if its counterpart is "higher". */
for (i = 1; i < 107; ++i) {
int w = work[i] & 0xffffff;
if ((w >= 1000) || (w && i < w))
++n;
}
if (n < result[0]) {
LOG("Best one so far at depth %d, todo %d:\n", depth, n);
print_raw(work);
memcpy(result
, work
, sizeof(int) * 107);
result[0] = n;
}
} else {
for (i = 0; i < 6 && (n = common_neighs[src][i][0]); ++i) {
int mid = g->b[common_neighs[src][i][1]] | g->b[common_neighs[src][i][2]];
/* Opponent is (partially) in the way, this destination is unsafe. */
if ((mid & 3) == (g->cur ^ 3))
continue;
if (work[common_neighs[src][i][1]] || work[common_neighs[src][i][2]])
continue;
if (!(mid & 3)) {
work[common_neighs[src][i][1]] = common_neighs[src][i][2];
work[common_neighs[src][i][2]] = common_neighs[src][i][1];
}
find_safe_path_int(g, n, dst, result, work, depth - 1);
if (!(mid & 3)) {
work[common_neighs[src][i][1]] = 0;
work[common_neighs[src][i][2]] = 0;
}
}
}
if (!(g->b[src] & g->cur))
work[src] -= 1000;
work[src] &= ~0x1000000;
}
int find_safe_path(struct game *g, int src, int dst, int result[107], int depth)
{
int work[107] = {};
int i;
result[0] = 999999;
find_safe_path_int(g, src, dst, result, work, depth);
if (result[0] > 100)
return 999999;
for (i = 1; i < 107; ++i)
result[i] &= ~0x1000000;
LOG("Safe path from %d to %d:\n", src, dst);
print_raw(result);
return result[0];
}
int find_clusters_int(struct game *g, int result[107], int pos)
{
int i, n;
int ret = 1;
result[pos] |= 0x100; /* Seen. */
for (i = 0; i < 6 && (n = neighs[pos][i]); ++i) {
if (!(result[n] & 0x100) && (g->b[n] & g->b[pos] & 3)) {
ret += find_clusters_int(g, result, n);
}
}
return ret;
}
void find_clusters(struct game *g, int result[107])
{
int i;
for (i = 1; i < 107; ++i) {
if (!(result[i] & 0x100) && (g->b[i] & 3)) {
result[i] = find_clusters_int(g, result, i);
LOG("Field size at %d: %d\n", i, result[i] &= 0xff);
}
}
}
void apply_move_update_edges(struct game *g, int pos, int new_edges)
{
int i, n;
g->b[pos] |= new_edges;
for (i = 0; i < 6 && (n = neighs[pos][i]); ++i)
if ((g->b[n] & g->cur) && (g->b[n] & new_edges) != new_edges)
apply_move_update_edges(g, n, new_edges);
}
void apply_move(struct game *g, int move)
{
if (move != -1) {
int i, n, new_edges = 0;
for (i = 0; i < 6 && (n = neighs[move][i]); ++i) {
if (!(g->b[n] & g->cur))
continue;
new_edges |= g->b[n];
}
new_edges |= g->b[move];
new_edges &= (0xff << EDGE_BITS);
for (i = 0; i < 6 && (n = neighs[move][i]); ++i) {
if (!(g->b[n] & g->cur))
continue;
if ((new_edges & g->b[n]) < new_edges)
apply_move_update_edges(g, n, new_edges);
}
g->b[move] |= g->cur | new_edges;
g->player_corners[g->cur] |= edge2corner[new_edges>>EDGE_BITS];
} else {
int i;
/* Don't bother checking whether this is turn 2, referee does it. */
for (i = 1; i < 107; ++i)
if ((g->b[i] & 3)) {
g->b[i] ^= 3;
break;
}
}
g->cur ^= 3;
++g->turn;
}
int find_winner(struct game *g)
{
int i;
for (i = 1; i <= 2; ++i)
if (enough_corners(g->player_corners[i])) {
printf("Player %d has WON!\n", i
);
return i;
}
return 0;
}
int follow_game(void)
{
struct game *g = new_game();
int move;
while(scanf("%d", &move
) == 1) {
apply_move(g, move);
print_board(g);
find_winner(g);
}
return 0;
}
void update_plans(struct game *g)
{
int a, b, c, i;
int path[107], best_path[107], path_len, best_len = 99999;
int fields[107];
if (!g->plans) {
g
->plans
= calloc(sizeof(struct plans
), 1);
}
if (g->plans->todolen) {
for (i = 0; i < g->plans->todolen; ++i) {
if (g->b[g->plans->todo[i]] & (3 ^ g->cur))
break;
}
/* Our plan should still work. */
if (i == g->plans->todolen && g->turn & 7)
return;
}
if (g->turn <= 20) {
//best_len = find_path_triple(g, 26, 100, 99, best_path);
//best_len = find_path_triple(g, 1, 103, 82, best_path);
//best_len = find_path_triple(g, 35, 89, 85, best_path);
best_len = find_path(g, start_path[0], start_path[1], best_path);
//best_len = find_path(g, 79, 105, best_path);
if (best_len > 20)
for (a = 0; edge_cells[a]; ++a) {
for (b = a + 1; edge_cells[b]; ++b) {
for (c = b; edge_cells[c]; ++c) {
if ((g->b[edge_cells[a]] | g->b[edge_cells[b]] | g->b[edge_cells[c]]) & (g->cur ^ 3))
continue;
if (!enough_corners(g->player_corners[g->cur] |
edge2corner[edges[edge_cells[a]] | edges[edge_cells[b]] | edges[edge_cells[c]]]))
continue;
if (b != c)
path_len = find_path_triple(g, edge_cells[a], edge_cells[b], edge_cells[c], path);
else
path_len = find_path(g, edge_cells[a], edge_cells[b], path);
if (path_len < best_len) {
LOG("Possible PLAN: %d|%d|%d in %d moves\n", edge_cells[a], edge_cells[b], edge_cells[c], path_len);
memcpy(best_path
, path
, sizeof(path
));
best_len = path_len;
}
}
}
}
} else {
int biggest = 0;
find_clusters(g, fields);
for (i = 2; i < 107; ++i)
if ((g->b[i] & g->cur) && fields[i] > fields[biggest])
biggest = i;
for (i = 0; i < corner_cells[i]; ++i) {
/* Might theoretically be disconnected.
if (g->b[corner_cells[i]] & 3)
continue;
*/
//if ((g->b[corner_cells[i]] &
path_len = find_path(g, biggest, corner_cells[i], path);
if (path_len > 0 && path_len < best_len) {
memcpy(best_path
, path
, sizeof(path
));
best_len = path_len;
}
LOG("Still interesting: %d in %d moves\n", corner_cells[i], path_len);
}
if (best_len > 5)
for (i = 0; i < edge_cells[i]; ++i) {
/* Might theoretically be disconnected.
if (g->b[corner_cells[i]] & 3)
continue;
*/
if (bits[edges[edge_cells[i]]] > 1) /* Skip corners */
continue;
if (!(((g->b[edge_cells[i]] & g->b[biggest]) >> EDGE_BITS) !=
(g->b[edge_cells[i]] >> EDGE_BITS)))
continue;
path_len = find_path(g, biggest, edge_cells[i], path);
if (path_len > 0 && path_len < best_len) {
memcpy(best_path
, path
, sizeof(path
));
best_len = path_len;
}
LOG("Still interesting: %d in %d moves\n", edge_cells[i], path_len);
}
}
if (best_len > 1000) {
LOG("Stuck :-(\n");
return;
}
memcpy(g
->plans
->todo
, best_path
, sizeof(best_path
));
g->plans->todolen = best_len;
LOG("NEW PLAN:");
for (i = 0; i < best_len; ++i)
LOG(" %d", best_path[i]);
LOG("\n");
}
void list_moves(struct game *g, int moves[107])
{
int i, j, n;
memset(moves
, 0, sizeof(int) * 107);
if (1 || g->cur == g->me) {
for (i = 0; i < g->plans->todolen; ++i)
if (!(g->b[g->plans->todo[i]] & 3)) {
moves[g->plans->todo[i]] = 50; //g->plans->todo[i] <= 49 ? 70 : 50;
for (j = 0; j < 6 && (n = neighs[g->plans->todo[i]][j]); ++j) {
if (!(g->b[n] & 3)) {
moves[n] += 5;
break;
}
}
}
} {
for (i = 1; i < 107; ++i) {
if (!(g->b[i] & 3)) {
for (j = 0; j < 6 && (n = neighs[i][j]); ++j) {
if (g->b[n] & g->cur) {
moves[i] += 1;
break;
}
}
}
}
}
}
int eval_move_int(struct game *g, int move, int cur)
{
int i, n;
int neigh_edges = 0, common_edges = 0x1f, n_neighs = 0;
int new_corners = 0;
int score = 0;
for (i = 0; i < 6 && (n = neighs[move][i]); ++i) {
if (g->b[n] & cur) {
neigh_edges |= g->b[n] >> EDGE_BITS;
common_edges &= g->b[n] >> EDGE_BITS;
++n_neighs;
}
}
common_edges &= neigh_edges; /* In case neighbours are all empty, it's still 0x1f. */
new_corners = edge2corner[neigh_edges | (g->b[move] >> EDGE_BITS)];
//LOG("%d %d %d %d %d %d %d\n", move, n_neighs, neigh_edges, common_edges, new_corners, g->player_corners[cur], enough_corners(new_corners | g->player_corners[cur]));
if (enough_corners(new_corners | g->player_corners[cur])) {
/* Winning move! \o/ No need to look further. */
return 1000000;
}
/* Slight preference for joining an existing "cluster". */
score += n_neighs;
score += 10 * bits[g->b[move] >> EDGE_BITS];
/* How many edges are getting connected by this move? */
if (neigh_edges > common_edges)
score += 100 * bits[neigh_edges ^ common_edges];
if (new_corners > g->player_corners[cur])
score += 1000 * bits[new_corners];
return score;
}
int eval_move(struct game *g, int move)
{
int my_score = eval_move_int(g, move, g->cur);
int their_score = eval_move_int(g, move, g->cur ^ 3);
// LOG("%d %d %d %d\n", move, g->cur, my_score, their_score);
/* I like to win. */
if (my_score == 1000000) {
return my_score;
}
/* Opponent *not* winning is nearly as important. */
if (their_score == 1000000) { // && (g->cur == g->me) && 0) {
return 8000;
}
return my_score + their_score;
}
int best_move(struct game *g, int depth, int *ret_eval)
{
static int move_stack[MAX_DEPTH_START+1];
int best_move_stack[MAX_DEPTH_START+1];
int moves[107] = {};
struct game g2[1];
int move, eval, best_eval = -10000000, best = 0, next_eval;
int opponent_wins = 0;
int n = 0;
list_moves(g, moves);
for (move = 1; move < 107; ++move) {
if (moves[move] == 0 || (g->b[move] & 3))
continue;
++n;
if (depth == max_depth)
memset(move_stack
, 0, sizeof(move_stack
));
eval = moves[move] += eval_move(g, move);
if (eval >= 8000 && eval < 10000)
++opponent_wins;
if (eval < 1000000 && eval > 0 && depth > 0) {
apply_move(g2, move);
best_move(g2, depth - 1, &next_eval);
eval -= 0.8 * next_eval;
}
if (eval > best_eval) {
memcpy(best_move_stack
, move_stack
, sizeof(move_stack
));
best = move;
best_eval = eval;
}
if (depth == max_depth) {
int i;
LOG("%3d %6d because", move, eval);
for (i = max_depth - 1; i >= 0; --i)
LOG(" %d", move_stack[i]);
LOG("\n");
}
}
if (opponent_wins > 1) {
/* To consider: If we can't possibly keep the opponent from
winning, don't even try and hope it's stupid. We might
eventually get to win ourselves. */
//best_eval = 1000;
}
memcpy(move_stack
, best_move_stack
, sizeof(move_stack
));
if (ret_eval)
*ret_eval = best ? best_eval : 0;
move_stack[depth] = best;
// if (g->turn >= 21)
// LOG("Best move (out of %d) for %d at depth %d is %d (eval %d)\n", n, g->cur, depth, best, best_eval);
return best;
}
void update_safe_todo_int(struct game *g, int src, int ihave, int todo[107], int *best, int c[2], int depth)
{
int newtodo[107];
int i, cell, st;
for (i = 0; (cell = edge_cells[i]); ++i) {
if (!enough_corners(edge2corner[ihave | edges[cell]]))
continue;
if (g->b[cell] & (g->cur ^ 3))
continue;
LOG("Try %d and %d\n", src, cell);
st = find_safe_path(g, src, cell, newtodo, depth);
if (st < *best) {
c[0] = src;
c[1] = cell;
*best = st;
memcpy(todo
, newtodo
, sizeof(newtodo
));
}
}
for (cell = 1; cell < 107; ++cell) {
int n
, free = 0, nedges
= 0;
if (!edge_neighs[cell][0])
continue;
if (g->b[cell] & (g->cur ^ 3))
continue;
for (i = 0; i < 3 && (n = edge_neighs[cell][i]); ++i) {
if (!(g->b[n] & (g->cur ^ 3)))
nedges |= edges[n];
}
continue;
if (!enough_corners(edge2corner[ihave | nedges]))
continue;
LOG("Try %d and %d\n", src, cell);
st = find_safe_path(g, src, cell, newtodo, depth);
if (st < *best) {
int j, n2;
for (i = 0; i < 3 && (n = edge_neighs[cell][i]); ++i) {
if (g->b[n] & (g->cur ^ 3))
continue;
for (j = i + 1; j < 3 && (n2 = edge_neighs[cell][j]); ++j) {
if (g->b[n2] & (g->cur ^ 3))
continue;
if (!((g->b[n] | g->b[n2]) & g->cur)) {
newtodo[n] = n2;
newtodo[n2] = n;
} else {
newtodo[n] = 1000;
newtodo[n2] = 1000;
}
}
}
*best = st;
memcpy(todo
, newtodo
, sizeof(newtodo
));
print_raw(todo);
c[0] = src;
c[1] = cell;
}
}
}
void update_safe_todo(struct game *g, int todo[107], int c[6])
{
int best = 999999;
int i, cell;
static int oldtodo[107]; /* Not threaded/nested anyway so whatever. */
if (g->plans->stage == ST_1LINE) {
if (find_safe_path(g, c[0], c[1], todo, 10) < 100)
return;
else
++g->plans->stage; /* Try to finish it somehow. */
}
if (g->plans->stage == ST_HALFLINE) {
/* Initial plan (one line/link to win) fully failed now.
See what we can make of it. */
int i, mid = 1;
/* Find the corner in between c[0-1]. */
for (i = 0; (cell = corner_cells[i]); ++i) {
if ((edges[cell] & edges[c[0]]) &&
(edges[cell] & edges[c[1]])) {
mid = cell;
break;
}
}
update_safe_todo_int(g, c[0], edges[c[0]], todo, &best, c + 2, 12);
update_safe_todo_int(g, c[1], edges[c[1]], todo, &best, c + 2, 12);
update_safe_todo_int(g, c[0], edges[c[0]] | (edges[c[1]] & ~edges[mid]), todo, &best, c + 2, 12);
update_safe_todo_int(g, c[1], edges[c[1]] | (edges[c[0]] & ~edges[mid]), todo, &best, c + 2, 12);
if (best < 100) {
print_raw(todo);
return;
}
}
if (g->plans->stage == ST_HALFLINE_DONE) {
/* We've finished the mandatory todo items, yet this function
was called. It means we need to draw another line. Remember
this one because it's still unfinished. */
memcpy(oldtodo
, todo
, sizeof(oldtodo
)); /* Urgh. */
++g->plans->stage;
}
if (g->plans->stage == ST_EXTRALINE) {
int ihave = edges[c[2]] | edges[c[3]] | edges[edge_neighs[c[3]][0]]
| edges[edge_neighs[c[3]][1]] | edges[edge_neighs[c[3]][2]];
update_safe_todo_int(g, c[2], ihave, todo, &best, c + 4, 12);
if (best < 100) {
LOG("MERGE %d %d %d %d %d %d\n", c[0], c[1], c[2], c[3], c[4], c[5]);
print_raw(todo);
print_raw(oldtodo);
for (i = 1; i < 107; ++i)
if (todo[i] >= 1000) {
/* Just leave it. */
} else if (oldtodo[i] && !todo[i])
todo[i] = oldtodo[i];
else if (oldtodo[i] && todo[i]) {
todo[todo[i]] = 0;
todo[oldtodo[i]] = 0;
oldtodo[todo[i]] = 0;
oldtodo[oldtodo[i]] = 0;
todo[i] = 1100;
}
print_raw(todo);
return;
}
}
g->plans->stage = ST_FAILED;
}
int play_game(char *start[])
{
struct game *g = new_game();
int move;
char move_s[16];
int i;
if (start) {
for (i = 0; start[i]; ++i) {
sscanf(start
[i
], "%d", &move
);
apply_move(g, move);
}
g->me = g->cur;
} else
g->me = 2;
while (1) {
if (g->cur != g->me) {
if (scanf("%s", move_s
) != 1)
break;
if (sscanf(move_s
, "%d", &move
) == 1) {
} else if (strcasecmp(move_s, "Quit") == 0) {
break;
} else if (strcasecmp(move_s, "Start") == 0) {
/* I'm white! */
g->me = 1;
continue;
}
if (!(move == -1 || (move >= 1 && move <= 106 && !(g->b[move] & 3)))) {
LOG("INVALID!\n");
continue;
}
} else if (g->plans->stage < ST_FAILED) {
static int c[6] = {};
static int todo[107] = {};
int last = move;
int n, j;
move = 0;
if (g->turn == 1) {
move = 1;
c[0] = 1;
} else if (g->turn == 2) {
if (bits[edges[last]] > 1) {
c[0] = last;
move = -1;
} else {
for (i = 0; corner_cells[i]; ++i) {
if (g->b[corner_cells[i]] & 3)
continue;
for (j = 0; j < 6 && (n = neighs[corner_cells[i]][j]); ++j)
if (g->b[n] & 3)
break;
if (n)
continue;
move = c[0] = corner_cells[i];
break;
}
}
} else if (last == -1) {
move = c[0] = 37;
} else if (!c[1]) {
for (i = 0; corner_cells[i]; ++i) {
if (g->b[corner_cells[i]] & 3)
continue;
for (j = 0; j < 6 && (n = neighs[corner_cells[i]][j]); ++j)
if (g->b[n] & 3)
break;
if (n)
continue;
if (edges[c[0]] & edges[corner_cells[i]])
continue;
move = c[1] = corner_cells[i];
break;
}
update_safe_todo(g, todo, c);
} else {
if (todo[last] >= 1000) {
/* Opponent stole a mandatory cell of our
planned path. Reroute. */
LOG("Need to reroute.\n");
update_safe_todo(g, todo, c);
} else if (todo[last]) {
/* Opponent chose a non-mandatory cell,
pick its alternative now. */
move = todo[last];
todo[last] = 0;
todo[move] = 0;
}
if (move == 0) {
for (i = 1; i < 107; ++i) {
if (!(g->b[i] & 3) && todo[i] >= 1000) {
/* Not very pretty code, this is meant
to detect whether any neighbour field
is owned by the opponent, continue if not. */
for (j = 0; j < 6 && (n = neighs[i][j]); ++j)
if (g->b[n] & (g->cur ^ 3))
break;
if (j == 6 || !n)
continue;
/* If the opponent has made a move
close to here recently, take this
cell now. */
move = i;
break;
}
}
}
if (move == 0) {
for (i = 1; i < 107; ++i) {
if (!(g->b[i] & 3) && todo[i] >= 1000 &&
(!move || todo[i] > todo[move]))
move = i;
}
}
if (move == 0 && g->plans->stage == ST_HALFLINE) {
/* Mandatory todo's finished, but we'll need to
think of some more things. */
++g->plans->stage;
update_safe_todo(g, todo, c);
}
/* REPEAT OF THE ABOVE: We've just updated the todo so
rescan for mandatory items. */
if (move == 0) {
for (i = 1; i < 107; ++i) {
if (!(g->b[i] & 3) && todo[i] >= 1000 &&
(!move || todo[i] > todo[move]))
move = i;
}
}
if (move == 0) {
for (i = 1; i < 107; ++i) {
if (!(g->b[i] & 3) && todo[i]) {
move = i;
todo[todo[move]] = 0;
todo[move] = 0;
break;
}
}
}
}
if (!move) {
move = 1;
g->plans->stage = ST_FAILED;
}
/* Ensure that the move is valid, unless we're debugging. */
if (!verbose || g->plans->stage == ST_FAILED)
while ((g->b[move] & 3))
move = (move % 106) + 1;
} else {
if (g->turn == 2 && edges[move] && (edges[move] & (edges[move] - 1)) > 0) {
/* Is this a corner and can we steal it? If so, let's do that,
because we can. :-) */
move = -1;
} else
move = 0;
if (move == 0 && *first_move) {
while (*first_move) {
if (!(g->b[*first_move] & 3)) {
move = *first_move;
break;
}
++first_move;
}
}
if (move == 0) {
update_plans(g);
move = best_move(g, max_depth, NULL);
}
/* Safeguard to ~ensure a valid move. */
if (move != -1)
while ((g->b[move] & 3))
move = (move % 106) + 1;
}
LOG("%s move: %d\n", g->cur == g->me ? "My" : "Opponent", move);
apply_move(g, move);
print_board(g);
if (find_winner(g)) {
if (find_winner(g) == g->me)
log_options("WIN");
/* To avoid "Could not write to stdin" error from referree
at shutdown time: */
usleep(100000);
break;
}
LOG
("CPU time so far: %f\n", ((float) clock()) / CLOCKS_PER_SEC
);
if (clock() / CLOCKS_PER_SEC
>= 20) {
LOG("Time is starting to run out, time to cut some corners.\n");
max_depth = MAX_DEPTH_START - 1;
}
}
return 0;
}
int main(int argc, char *argv[])
{
char **test = NULL;
char *s;
pick_options();
verbose = 1;
if (argc
> 1 && strcmp(argv
[1], "follow") == 0) {
return follow_game();
}
if (argc
> 1 && strcmp(argv
[1], "test") == 0) {
test = argv + 2;
}
return play_game(test);
}