├── html
├── favicon.ico
├── sheep_map
│ ├── images
│ │ ├── 0.png
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ ├── 9.png
│ │ ├── 10.png
│ │ ├── 11.png
│ │ ├── 12.png
│ │ ├── 13.png
│ │ ├── 14.png
│ │ ├── 15.png
│ │ ├── 16.png
│ │ ├── pre.png
│ │ ├── mask
│ │ │ ├── 0.png
│ │ │ ├── 1.png
│ │ │ ├── 2.png
│ │ │ ├── 3.png
│ │ │ ├── 4.png
│ │ │ ├── 5.png
│ │ │ ├── 6.png
│ │ │ ├── 7.png
│ │ │ ├── 8.png
│ │ │ ├── 9.png
│ │ │ ├── 10.png
│ │ │ ├── 11.png
│ │ │ ├── 12.png
│ │ │ ├── 13.png
│ │ │ ├── 14.png
│ │ │ ├── 15.png
│ │ │ └── 16.png
│ │ ├── next.png
│ │ └── side.png
│ ├── main.css
│ ├── index.php
│ ├── map_data.php
│ ├── index.html
│ └── map_data.js
└── index.php
├── requirements.txt
├── mitmweb_ylgy.sh
├── item
├── __pycache__
│ ├── Card.cpython-39.pyc
│ ├── CardPosition.cpython-39.pyc
│ └── ResidualPool.cpython-39.pyc
├── ResidualPool.py
├── Card.py
└── CardPosition.py
├── 关卡地图数据库文件
├── 20221022-2204-20221024-1755.db
└── 20221025-0417-20221026-1451.db
├── hepler
├── __pycache__
│ └── FileHelper.cpython-39.pyc
└── FileHelper.py
├── .gitignore
├── shuffle.js
├── readme.md
├── autoSolve.py
├── sheep_manual.py
├── business
└── SheepSolver.py
└── sheep.py
/html/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/favicon.ico
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | func_timeout==4.3.5
2 | mitmproxy==8.1.0
3 | PyExecJS==1.5.1
4 | requests==2.26.0
5 |
--------------------------------------------------------------------------------
/html/sheep_map/images/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/0.png
--------------------------------------------------------------------------------
/html/sheep_map/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/1.png
--------------------------------------------------------------------------------
/html/sheep_map/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/2.png
--------------------------------------------------------------------------------
/html/sheep_map/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/3.png
--------------------------------------------------------------------------------
/html/sheep_map/images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/4.png
--------------------------------------------------------------------------------
/html/sheep_map/images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/5.png
--------------------------------------------------------------------------------
/html/sheep_map/images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/6.png
--------------------------------------------------------------------------------
/html/sheep_map/images/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/7.png
--------------------------------------------------------------------------------
/html/sheep_map/images/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/8.png
--------------------------------------------------------------------------------
/html/sheep_map/images/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/9.png
--------------------------------------------------------------------------------
/html/sheep_map/images/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/10.png
--------------------------------------------------------------------------------
/html/sheep_map/images/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/11.png
--------------------------------------------------------------------------------
/html/sheep_map/images/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/12.png
--------------------------------------------------------------------------------
/html/sheep_map/images/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/13.png
--------------------------------------------------------------------------------
/html/sheep_map/images/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/14.png
--------------------------------------------------------------------------------
/html/sheep_map/images/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/15.png
--------------------------------------------------------------------------------
/html/sheep_map/images/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/16.png
--------------------------------------------------------------------------------
/html/sheep_map/images/pre.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/pre.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/0.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/1.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/2.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/3.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/4.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/5.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/6.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/7.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/8.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/9.png
--------------------------------------------------------------------------------
/html/sheep_map/images/next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/next.png
--------------------------------------------------------------------------------
/html/sheep_map/images/side.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/side.png
--------------------------------------------------------------------------------
/mitmweb_ylgy.sh:
--------------------------------------------------------------------------------
1 | /usr/bin/mitmweb -p 9998 -s sheep.py --web-port 9999 --web-iface 0.0.0.0 --set block_global=false
2 |
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/10.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/11.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/12.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/13.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/14.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/15.png
--------------------------------------------------------------------------------
/html/sheep_map/images/mask/16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/html/sheep_map/images/mask/16.png
--------------------------------------------------------------------------------
/item/__pycache__/Card.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/item/__pycache__/Card.cpython-39.pyc
--------------------------------------------------------------------------------
/关卡地图数据库文件/20221022-2204-20221024-1755.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/关卡地图数据库文件/20221022-2204-20221024-1755.db
--------------------------------------------------------------------------------
/关卡地图数据库文件/20221025-0417-20221026-1451.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/关卡地图数据库文件/20221025-0417-20221026-1451.db
--------------------------------------------------------------------------------
/hepler/__pycache__/FileHelper.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/hepler/__pycache__/FileHelper.cpython-39.pyc
--------------------------------------------------------------------------------
/item/__pycache__/CardPosition.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/item/__pycache__/CardPosition.cpython-39.pyc
--------------------------------------------------------------------------------
/item/__pycache__/ResidualPool.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/longhuan1999/sheep/HEAD/item/__pycache__/ResidualPool.cpython-39.pyc
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .idea/
3 | node_modules/
4 | *.json
5 | !config.json
6 | test.py
7 | __pycache__/
8 | business/__pycache__/
9 | html/sheep_map/test.html
10 | html/test.html
11 | html/sheep_maps.db
12 | html/*.py
13 |
--------------------------------------------------------------------------------
/hepler/FileHelper.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os.path
3 |
4 |
5 | class FileHelper(object):
6 | def read_json_data(self, file_path):
7 | file_content = self.read_file_content(file_path) or "null"
8 | return json.loads(file_content)
9 |
10 | @staticmethod
11 | def read_file_content(file_path):
12 | try:
13 | if os.path.exists(file_path):
14 | reader = open(file_path, "r")
15 | content = reader.read()
16 | reader.close()
17 | return content
18 | else:
19 | return None
20 | except Exception as e:
21 | return None
22 |
--------------------------------------------------------------------------------
/item/ResidualPool.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | class ResidualPool(object):
5 | def __init__(self):
6 | # 当前操作池有多少张卡牌
7 | self._pool_count = 0
8 | # 当前操作池可容纳的最大牌数
9 | self._pool_limit = 7
10 | # 当前操作池帕牌类别及数量
11 | self._pool_card = {}
12 |
13 | def is_pool_full(self):
14 | return len(self._pool_card.keys()) >= 6 or self._pool_count >= self._pool_limit
15 |
16 | def show_pool_state(self):
17 | return "count: {}, detail: {}".format(self._pool_count, json.dumps(self._pool_card))
18 |
19 | def pick_card(self, card_detail):
20 | self._pool_count += 1
21 | card_type = card_detail.get_type()
22 | if card_type in self._pool_card:
23 | self._pool_card[card_type] += 1
24 | else:
25 | self._pool_card[card_type] = 1
26 | self._make_card_disappear(card_type)
27 |
28 | def recover_card(self, card_detail):
29 | card_type = card_detail.get_type()
30 | if card_type in self._pool_card:
31 | if self._pool_card[card_type] == 1:
32 | self._pool_card.pop(card_type)
33 | else:
34 | self._pool_card[card_type] -= 1
35 | self._pool_count -= 1
36 | else:
37 | self._pool_card[card_type] = 2
38 | self._pool_count += 2
39 |
40 | def _make_card_disappear(self, card_type):
41 | if self._pool_card[card_type] == 3:
42 | self._pool_count -= 3
43 | self._pool_card.pop(card_type)
44 |
--------------------------------------------------------------------------------
/html/sheep_map/main.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | background-color: #000;
4 | color: #fff;
5 | font-family: Monospace;
6 | font-size: 13px;
7 | line-height: 24px;
8 | overscroll-behavior: none;
9 | }
10 |
11 | a {
12 | color: #ff0;
13 | text-decoration: none;
14 | }
15 |
16 | a:hover {
17 | text-decoration: underline;
18 | }
19 |
20 | button {
21 | cursor: pointer;
22 | text-transform: uppercase;
23 | }
24 |
25 | #info {
26 | position: absolute;
27 | top: 0px;
28 | width: 100%;
29 | padding: 10px;
30 | box-sizing: border-box;
31 | text-align: center;
32 | -moz-user-select: none;
33 | -webkit-user-select: none;
34 | -ms-user-select: none;
35 | user-select: none;
36 | pointer-events: none;
37 | z-index: 1; /* TODO Solve this in HTML */
38 | }
39 |
40 | a, button, input, select {
41 | pointer-events: auto;
42 | }
43 |
44 | .lil-gui {
45 | z-index: 2 !important; /* TODO Solve this in HTML */
46 | }
47 |
48 | @media all and ( max-width: 640px ) {
49 | .lil-gui.root {
50 | right: auto;
51 | top: auto;
52 | max-height: 50%;
53 | max-width: 80%;
54 | bottom: 0;
55 | left: 0;
56 | }
57 | }
58 |
59 | #overlay {
60 | position: absolute;
61 | font-size: 16px;
62 | z-index: 2;
63 | top: 0;
64 | left: 0;
65 | width: 100%;
66 | height: 100%;
67 | display: flex;
68 | align-items: center;
69 | justify-content: center;
70 | flex-direction: column;
71 | background: rgba(0,0,0,0.7);
72 | }
73 |
74 | #overlay button {
75 | background: transparent;
76 | border: 0;
77 | border: 1px solid rgb(255, 255, 255);
78 | border-radius: 4px;
79 | color: #ffffff;
80 | padding: 12px 18px;
81 | text-transform: uppercase;
82 | cursor: pointer;
83 | }
84 |
85 | #notSupported {
86 | width: 50%;
87 | margin: auto;
88 | background-color: #f00;
89 | margin-top: 20px;
90 | padding: 10px;
91 | }
92 |
--------------------------------------------------------------------------------
/item/Card.py:
--------------------------------------------------------------------------------
1 | class Card(object):
2 | def __init__(self, origin_data):
3 | self._origin_data = origin_data
4 | self._parent_note = set()
5 | self._children_node = set()
6 |
7 | def get_type(self):
8 | return self._origin_data["type"]
9 |
10 | def clac_area(self):
11 | width = self._origin_data["max_x"] - self._origin_data["min_x"]
12 | height = self._origin_data["max_y"] - self._origin_data["min_y"]
13 | return width * height
14 |
15 | def get_position(self):
16 | return [self._origin_data["min_x"], self._origin_data["min_y"],
17 | self._origin_data["max_x"], self._origin_data["max_y"]]
18 |
19 | def clac_iou(self, card):
20 | current_position = self.get_position()
21 | other_position = card.get_position()
22 | min_x = max(current_position[0], other_position[0])
23 | min_y = max(current_position[1], other_position[1])
24 | max_x = min(current_position[2], other_position[2])
25 | max_y = min(current_position[3], other_position[3])
26 | overlap_area = max(0, max_x - min_x) * max(0, max_y - min_y)
27 | current_area = self.clac_area()
28 | other_area = card.clac_area()
29 | return overlap_area / (current_area + other_area - overlap_area)
30 |
31 | def has_parent(self):
32 | return len(self._parent_note) > 0
33 |
34 | def get_children_set(self):
35 | return self._children_node
36 |
37 | def add_parent(self, card_index):
38 | self._parent_note.add(card_index)
39 |
40 | def recover_parent(self, card_index):
41 | self._parent_note.remove(card_index)
42 |
43 | def add_children(self, card_index):
44 | self._children_node.add(card_index)
45 |
46 | def recover_children(self, card_index):
47 | self._children_node.remove(card_index)
48 |
--------------------------------------------------------------------------------
/shuffle.js:
--------------------------------------------------------------------------------
1 |
2 | // 生成随机数的类
3 | var XorShift = function() {
4 | function t() {}
5 | return Object.defineProperty(t, "instance", {
6 | get: function() {
7 | return this._instance || (this._instance = new t()), this._instance;
8 | },
9 | enumerable: !1,
10 | configurable: !0
11 | }), t.prototype.setSeed = function(t) {
12 | if (!Array.isArray(t) || 4 !== t.length) throw new TypeError("seed must be an array with 4 numbers");
13 | this._state0U = 0 | t[0], this._state0L = 0 | t[1], this._state1U = 0 | t[2], this._state1L = 0 | t[3];
14 | }, t.prototype.randomint = function() {
15 | var t = this._state0U, e = this._state0L, o = this._state1U, n = this._state1L, i = (n >>> 0) + (e >>> 0), a = o + t + (i / 2 >>> 31) >>> 0, r = i >>> 0;
16 | this._state0U = o, this._state0L = n;
17 | var c = 0, s = 0;
18 | return c = (t ^= c = t << 23 | (-512 & e) >>> 9) ^ o, s = (e ^= s = e << 23) ^ n,
19 | c ^= t >>> 18, s ^= e >>> 18 | (262143 & t) << 14, c ^= o >>> 5, s ^= n >>> 5 | (31 & o) << 27,
20 | this._state1U = c, this._state1L = s, [ a, r ];
21 | }, t.prototype.random = function() {
22 | var t = this.randomint();
23 | return 2.3283064365386963e-10 * t[0] + 2.220446049250313e-16 * (t[1] >>> 12);
24 | }, t._instance = null, t;
25 | }();
26 |
27 | // 打乱数组的方法
28 | function shuffle(array, seed=null) {
29 | var xorshift = XorShift.instance;
30 | if (seed != null) {
31 | // 设置随机种子
32 | xorshift.setSeed(seed);
33 | // 先获取一次随机值
34 | xorshift.random();
35 | }
36 | // 数组下标从后往前遍历
37 | for (var i = array.length - 1; i >= 0; i--) {
38 | // 获取0到1之间的随机值
39 | var random = xorshift.random();
40 | // 计算出随机的下标
41 | var j = Math.floor(random * (i + 1));
42 | // 交换两个下标
43 | var temp = array[j];
44 | array[j] = array[i];
45 | array[i] = temp;
46 | }
47 | // 将数组反序排列
48 | array.reverse();
49 | return array;
50 | }
51 |
--------------------------------------------------------------------------------
/item/CardPosition.py:
--------------------------------------------------------------------------------
1 | class CardPosition(object):
2 | def __init__(self):
3 | # 以序号注册所有卡牌数据
4 | self._origin_data = {}
5 | # 以序号注册可操作卡牌数据
6 | self._head_data = {}
7 | # 当前登记的序号
8 | self._card_count = 0
9 |
10 | def append_level_card(self, card_list):
11 | start_index = len(self._origin_data) + 1
12 | self._append_origin_data(card_list)
13 | end_index = len(self._origin_data) + 1
14 | new_card_data = {key: self._origin_data[key] for key in range(start_index, end_index)}
15 | self._handle_overlap_data(new_card_data)
16 |
17 | def generate_head_data(self):
18 | for key_old, card_old in self._origin_data.items():
19 | if not card_old.has_parent():
20 | self._head_data[key_old] = card_old
21 |
22 | def get_head_description(self):
23 | return "-".join([str(item) for item in sorted(self._head_data.keys())])
24 |
25 | def get_card_detail(self, card_index):
26 | return self._origin_data[card_index]
27 |
28 | def pick_card(self, card_index):
29 | self._head_data.pop(card_index)
30 | children_set = self._origin_data[card_index].get_children_set()
31 | for children_key in children_set:
32 | children_item = self._origin_data[children_key]
33 | children_item.recover_parent(card_index)
34 | if not children_item.has_parent():
35 | self._head_data[children_key] = children_item
36 |
37 | def recover_card(self, card_index):
38 | card_detail = self._origin_data[card_index]
39 | self._head_data[card_index] = card_detail
40 | children_set = card_detail.get_children_set()
41 | for children_key in children_set:
42 | children_item = self._origin_data[children_key]
43 | children_item.add_parent(card_index)
44 | if children_key in self._head_data:
45 | self._head_data.pop(children_key)
46 |
47 | def get_head_key_list(self):
48 | return list(self._head_data.keys())
49 |
50 | def is_head_data_empty(self):
51 | return len(self._head_data.keys()) == 0
52 |
53 | def _append_origin_data(self, card_list):
54 | for card_item in card_list:
55 | self._card_count += 1
56 | self._origin_data[self._card_count] = card_item
57 |
58 | def _handle_overlap_data(self, card_dict):
59 | old_card_dict = {key: self._origin_data[key] for key in self._origin_data.keys() if key not in card_dict}
60 | for key_new, card_new in card_dict.items():
61 | for key_old, card_old in old_card_dict.items():
62 | if card_new.clac_iou(card_old) > 0:
63 | card_new.add_children(key_old)
64 | card_old.add_parent(key_new)
--------------------------------------------------------------------------------
/html/sheep_map/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 羊了个羊3D地图
5 |
6 |
7 |
8 |
40 |
41 |
49 |
50 |
51 |
52 |
57 |
58 |
59 |
60 | 0){//判断是否有Get参数
62 | if(isset($_GET["id"])){//判断所需要的参数是否存在,isset用来检测变量是否设置,返回true or false
63 | $id = $_GET["id"];//存在
64 | echo "\n";
65 | } else {
66 | echo "\n";
67 | }
68 | } else {
69 | echo "\n";
70 | }
71 | ?>
72 |
73 |
--------------------------------------------------------------------------------
/html/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 羊了个羊3D地图
5 |
6 |
7 |
8 | open('sheep_maps.db');
33 | }
34 | }
35 | $db = new MyDB();
36 | if(!$db){
37 | echo "\n\t";
38 | //echo $db->lastErrorMsg();
39 | } else {
40 | echo "\n\t";
41 | //echo "成功创建或打开数据文件\n";
42 | }
43 |
44 | $sql1 =<<exec($sql1);
54 | if(!$ret1){
55 | echo "\n\t";
56 | //echo $db->lastErrorMsg();
57 | } else {
58 | echo "\n\t";
59 | //echo "成功创建或检查数据表\n";
60 | }
61 |
62 | $req_json_str = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
63 | //echo gettype($req_json_str);
64 | if(strpos($req_json_str, "levelData") !== false && strpos($req_json_str, "layers") !== false){
65 | $ret4 = $db->query("SELECT ID FROM MAPS WHERE MAP_INFO = '$req_json_str'");
66 | while($row = $ret4->fetchArray()){
67 | $ID = $row["ID"];
68 | }
69 | if($ID == null){
70 | $sql2 = "INSERT INTO MAPS (MAP_INFO,IP,DATA_TIME) VALUES ('$req_json_str','$ip','$data_time')";
71 | $ret2 = $db->exec($sql2);
72 | $ret3 = $db->query("SELECT MAX(ID) from MAPS");
73 | if(!$ret2){
74 | echo "\n\t";
75 | //echo $db->lastErrorMsg();
76 | } else {
77 | echo "\n\t";
78 | //echo "成功插入数据\n";
79 | while($row = $ret3->fetchArray() ){
80 | $ID = $row["MAX(ID)"];
81 | }
82 | }
83 | }
84 | }
85 | if($ID == null){
86 | echo "访问示例3D地图\n\t";
87 | echo "\n";
88 | } else {
89 | echo "访问当前关卡3D地图\n\t";
90 | echo "\n";
91 | }
92 | $db->close();
93 | ?>
94 |
95 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | > 关卡数据中的解答步骤字段名 "oprations" 已纠正为 "operations",请使用最新项目!
2 | [https://ylgy.endless084.top](https://ylgy.endless084.top) 做了兼容,提交的关卡数据中的解答步骤字段名还是 "oprations" 也能查看3D地图解答,但会有弹窗提示。
3 |
4 | > **求解算法来自 [NB-Dragon/SheepSolver](https://github.com/NB-Dragon/SheepSolver) ,5分钟内求解成功率暂时不高
5 | 经过一些调整和测试,四种模式同时尝试(已添加到抓包脚本中)有一定概率在短时间内得到解,甚至是多解,建议超过60~90秒就放弃重试!**
6 | 
7 |
8 |
9 | ### 一、运行环境
10 |
11 | #### 1、Python3
12 |
13 | 推荐使用`Anaconda`进行安装,官网:[https://www.anaconda.com](https://www.anaconda.com/) 。
14 |
15 | #### 2、Node.js
16 |
17 | 用来防止`pyExecJs`库报错,也可以用来安装网页服务器,官网:[https://nodejs.org/zh-cn/download](https://nodejs.org/zh-cn/download) 。
18 |
19 | #### 3、Git
20 |
21 | Windows系统需要手动安装`git`,官网:[https://gitforwindows.org](https://gitforwindows.org) 。
22 |
23 | #### 4、Web服务器(任选一种)
24 |
25 | (一)使用`nginx`或`apache`等 Web服务搭配`php`环境以及`sqlite`数据库,具体可以百度
26 |
27 | 搭建好 Web服务环境后需要将`autoSolve.py`中`post_map_data`函数中的服务器地址换成你自己的。
28 |
29 | > **也可以不换直接用我写好的的也行:[https://ylgy.endless084.top](https://ylgy.endless084.top)**
30 |
31 | 本人因为想将3d地图放在 vps 上,所以使用的是 nginx 虚拟主机(域名)搭配 php 环境,mitmproxy 抓包放在了本地电脑上。
32 |
33 | (二)使用`Node.js`
34 |
35 | 安装网页服务器:
36 | ```
37 | npm install -g live-server
38 | ```
39 |
40 | 启动网页服务器,在本项目目录下分别执行以下命令启动网页服务器:
41 | ```
42 | cd html/sheep_map
43 | # Windows: cd html\sheep_map
44 | live-server
45 | ```
46 |
47 | 执行后会浏览器会自动打开3d地图网页。算出解后刷新网页,就可以看到最新的游戏3d地图了。
48 |
49 | ---
50 |
51 | ### 二、克隆本项目
52 |
53 | 使用以下命令将本项目克隆到本地,并进入项目目录:
54 | ```
55 | git clone https://github.com/longhuan1999/sheep.git
56 | cd sheep
57 | ```
58 |
59 | > MacOS系统使用终端执行,Windows系统使用Powershell。
60 |
61 | ---
62 |
63 | ### 三、mitmproxy的配置
64 |
65 | [mitmproxy](https://github.com/mitmproxy/mitmproxy)是一个开源的抓包工具,可以加载自己写的Python代码进行数据处理。
66 |
67 | 目测不支持国外vps抓包,游戏会检测ip的地理位置。
68 |
69 | #### 1、安装
70 |
71 | 安装Python3后,执行以下命令安装mitmproxy、pyExecJs和requests:
72 | ```
73 | pip install mitmproxy pyExecJs requests
74 | ```
75 |
76 | #### 2、启动
77 |
78 | 新开一个终端,切换到本项目目录,执行以下命令启动抓包工具并加载`sheep.py`插件:
79 | ```
80 | mitmweb -p 6666 -s sheep.py
81 | # 默认代理端口是8080,默认web端口是8081,如果出现端口占用情况,参考以下参数
82 | # -p [代理端口]
83 | # --web-port [web端口]
84 | # --web-iface 或 --web-host [web主机名]
85 | # 示例:
86 | mitmweb -p 9998 -s sheep.py --web-port 9999 --web-iface 0.0.0.0
87 | mitmweb -p 9998 -s sheep.py --web-port 9999 --web-host 0.0.0.0
88 | ```
89 |
90 | 执行后浏览器会弹出一个抓包的网页界面。
91 |
92 | 接下来使用手机连接电脑的ip以及使用指定端口端口作为代理,就可以抓包了。
93 |
94 | >设置代理可以参考视频教程 [【4分钟教会你Charles抓包设置抓取电脑HTTPS以及IOS手机抓包-哔哩哔哩】](https://b23.tv/S0d8iYa) 两分钟的地方。
95 |
96 | #### 3、安装证书
97 |
98 | 使用手机浏览器访问 [http://mitm.it](http://mitm.it) 安装`mitmproxy`的证书。
99 |
100 | 苹果手机需要在 设置 - 通用 - 关于本机 - 证书信任设置 里信任证书。
101 |
102 | 如果安卓手机安装不了证书,也可以使用电脑的夜神模拟器,安装安卓5系统。
103 |
104 | 也可以使用Windows版微信的小程序。
105 |
106 | #### 4、使用
107 |
108 | 因为关卡`原始地图数据`(`map_data.txt`)每天只会请求一次,所以可以先删除游戏再重新进入。
109 |
110 | ~~手机进入游戏后,电脑刷新网页,就可以看到最新的游戏3d地图了。~~
111 |
112 | 目测不支持抖音小游戏版抓包,微信小游戏版支持。
113 |
114 | 主页面的`再次挑战`会重新打乱地图,但`关卡原始地图数据`不会刷新。
115 |
116 | 你可以在命令行的输出中看出地图是否刷新,3d地图的网页地址也会在命令行输出:
117 |
118 | 
119 |
120 | ---
121 |
122 | ### 四、游戏数据
123 |
124 | 目录`关卡地图数据库文件`中是一些保存了真实游戏关卡数据的数据库文件,可以用数据库管理软件打开查看。
125 |
126 | 文件`html/sheep_map/map_data.js`里面保存着最近一次游戏的关卡数据。
127 |
128 | 文件`html/sheep_maps.db`里面是php版生成的最近100次游戏的关卡数据。
129 |
130 | 大致说明一下字段的含义:
131 |
132 | ``` json
133 | {
134 | "widthNum": 8,
135 | "heightNum": 10,
136 | "levelKey": 90029,
137 | "blockTypeData": { //图案类型对应组数
138 | "1": 6, //图案1有6*3=18个
139 | "2": 6,
140 | "3": 6,
141 | "4": 6,
142 | "5": 5
143 | },
144 | "levelData": { //关卡数据
145 | "1": [ //第1层,也就是最底层
146 | {
147 | "id": "1-24-8", //方块id
148 | "type": 2, //图案类型
149 | "rolNum": 24, //x坐标
150 | "rowNum": 8, //y坐标
151 | "layerNum": 1, //层数
152 | "moldType": 1,
153 | "blockNode": null
154 | }
155 |
156 | //......
157 | ]
158 | },
159 | "layers": [ //排序后的层数
160 | "1",
161 | "2",
162 | "3",
163 | "4",
164 | "5"
165 | ],
166 | "operations": [ //自动求解步骤
167 | "21-12-28", //方块id
168 | "20-44-20",
169 | "13-44-12",
170 | "21-44-28",
171 | "16-44-40",
172 | "13-20-12",
173 | "17-28-24",
174 | "14-24-40"
175 | //......
176 | ]
177 | }
178 | ```
179 |
180 | 地图原点在左上角,方块的大小是`8 * 8`,有了这些数据就可以尝试写算法求解了。
181 |
182 | 如果得到了求解步骤,可以将求解步骤保存到operations字段,内容为依次点击的方块id,网页可以自动显示求解步骤。
183 |
--------------------------------------------------------------------------------
/autoSolve.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import time
3 | import json
4 | import argparse
5 | import os
6 | import threading
7 | import ctypes
8 | import inspect
9 | #from func_timeout.exceptions import FunctionTimedOut
10 | from business.SheepSolver import SheepSolver
11 |
12 |
13 | def _async_raise(tid, exctype):
14 | """raises the exception, performs cleanup if needed"""
15 | tid = ctypes.c_long(tid)
16 | if not inspect.isclass(exctype):
17 | exctype = type(exctype)
18 | res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
19 | if res == 0:
20 | raise ValueError("invalid thread id")
21 | elif res != 1:
22 | # """if it returns a number greater than one, you're in trouble,
23 | # and you should call it again with exc=NULL to revert the effect"""
24 | ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
25 | raise SystemError("PyThreadState_SetAsyncExc failed")
26 |
27 |
28 | def stop_thread(thread):
29 | _async_raise(thread.ident, SystemExit)
30 |
31 |
32 | def auto_solve(map_data, issort, percent, timeout, threadName):
33 | # 自动求解
34 | sheep_solver = SheepSolver(map_data)
35 | sheep_solver.init_card_data()
36 | start_time = time.time()
37 | #try:
38 | thread1 = threading.Thread(target=sheep_solver.solve, name=threadName, args=(issort, percent,))
39 | #sheep_solver.solve(issort, percent)
40 | thread1.start()
41 | second = 0
42 | # while second < 13:
43 | # time.sleep(1)
44 | # second += 1
45 | # print("\r进度:%d/300"%second,end="")
46 | while True:
47 | #if (second-10)%5 == 0:
48 | if second%2 == 0:
49 | if thread1.is_alive() is False:
50 | break
51 | elif second >= timeout:
52 | if thread1.is_alive():
53 | stop_thread(thread1)
54 | print("\033[0;33;40m自动求解超时!当前算法有些力不从心,建议放弃挑战并重新开始!\033[0m")
55 | print("==========================================")
56 | exit(0)
57 | time.sleep(1)
58 | second += 1
59 | print("\r\033[0;31;40m%s进度:\033[0m%d/%d"%(threadName, second, timeout),end="")
60 | #except FunctionTimedOut:
61 | #print("自动求解超时!当前算法有些力不从心,建议放弃挑战并重新开始!")
62 | #self.post_map_data(map_data)
63 | #else:
64 | end_time = time.time()
65 | result = sheep_solver.get_result()
66 | if result != "牌面无解":
67 | print("\033[0;32;40m计算用时:\033[0m\033[0;34;40m {:.2f}\033[0m".format(end_time - start_time))
68 | with open("map_data_operations.json","w",encoding="utf8") as f:
69 | f.write(json.dumps(result, indent=4))
70 | with open("html/sheep_map/map_data.js","w",encoding="utf8") as f:
71 | f.write(f"const map_data = {json.dumps(result, indent=4)};")
72 | print("当前关卡自动求解步骤已保存到当前路径下 map_data_operations.json 文件!")
73 | print("==========================================")
74 | post_map_data(result)
75 | else:
76 | print("\033[0;33;40m牌面无解!建议放弃挑战并重新开始!\033[0m")
77 | print("==========================================")
78 | #self.post_map_data(map_data)
79 |
80 |
81 | def post_map_data(map_data):
82 | # 提交关卡地图数据
83 | r = requests.post("https://ylgy.endless084.top", data=json.dumps(map_data, indent=4), headers={'Content-Type': 'application/json'}, verify=False)
84 | r_str = r.text
85 | url = r_str[r_str.rindex("sheep_map"):r_str.rindex("'")]
86 | if "id" not in url:
87 | print(r_str)
88 | print("\n\033[0;33;40m3D地图生成失败!\033[0m")
89 | else:
90 | url = "https://ylgy.endless084.top/%s"%url
91 | print("\033[0;32;40m当前关卡3D地图地址:\033[0m\033[0;34;40m%s\033[0m"%url)
92 |
93 |
94 | if __name__ == '__main__':
95 | parser = argparse.ArgumentParser(description='羊了个羊自动求解')
96 | parser.add_argument('-s', '--issort', dest='issort', type=str, default="", help="是否对可选牌进行排序,默认不排序。\ntrue:从小到大排序\nreverse:从大到小排序\n为空或者其他:不排序")
97 | parser.add_argument('-p', '--percent', dest='percent', type=float, default=0.85, help="进度超过多少时优先移除已有两张相同类型的手牌,取值范围0~1。")
98 | parser.add_argument('-i', '--input', dest='input', type=str, default="map_data.json", help="关卡json数据文件路径,默认当前路径下 map_data.json。")
99 | parser.add_argument('-t', '--timeout', dest='timeout', type=int, default=60, help="自动求解超时时间,单位秒")
100 | args = parser.parse_args()
101 | if os.path.isfile(args.input):
102 | with open(args.input, "r", encoding="utf8") as f:
103 | try:
104 | map_data = json.loads(f.read())
105 | except:
106 | input("文件 %s 内容格式错误,无法读取,请确保文件内容为JSON!"%args.input)
107 | exit(1)
108 | else:
109 | input("文件 %s 不存在,请检查路径!"%args.input)
110 | exit(1)
111 | if args.percent > 1 or args.percent < 0:
112 | input("参数 percent[p] 取值范围为 0~1 !"%args.input)
113 | exit(1)
114 | if args.issort != "true" and args.issort != "reverse" and args.percent == 0.85:
115 | threadName = "普通模式"
116 | elif args.issort == "reverse" and args.percent == 0.85:
117 | threadName = "高层优先模式"
118 | elif args.issort != "true" and args.issort != "reverse" and args.percent == 0:
119 | threadName = "优先移除两张相同类型的手牌模式"
120 | elif args.issort == "reverse" and args.percent == 0:
121 | threadName = "高层优先且优先移除两张相同类型的手牌模式"
122 | else:
123 | threadName = "自定义模式"
124 | print("开始求解,请稍等%d秒..."%args.timeout)
125 | auto_solve(map_data, args.issort, args.percent, args.timeout, threadName)
--------------------------------------------------------------------------------
/sheep_manual.py:
--------------------------------------------------------------------------------
1 | from os.path import isfile
2 | from autoSolve import auto_solve
3 | from subprocess import Popen, PIPE, STDOUT
4 | import execjs
5 | import json
6 | import _thread
7 |
8 |
9 | def cmd(command):
10 | subp = Popen(args=command, shell=True, encoding='utf8', stdin=PIPE, stdout=PIPE, stderr=STDOUT)
11 | subp.wait()
12 | if subp.poll() == 0:
13 | output = ""
14 | for i in (subp.communicate()[0]).split("\n"):
15 | if "进度" in i and output == "":
16 | output += "\n%s:\033[0m"%i[:i.index("进度")]
17 | elif "超时" in i:
18 | output += "\033[0;33;40m%s"%i[i.index("自动求解超时"):]
19 | elif "无解" in i:
20 | output += "\033[0;33;40m%s"%i[i.index("牌面无解"):]
21 | elif "计算用时" in i:
22 | output += "\033[0;32;40m%s | "%i[i.index("计算用时"):]
23 | elif "当前关卡3D地图地址" in i:
24 | output += "%s"%i
25 | elif "地图生成失败" in i:
26 | output += "%s"%i
27 | print(output)
28 | else:
29 | print("失败")
30 | print(subp.communicate()[0])
31 |
32 |
33 | js_code = open("shuffle.js", encoding="utf-8").read()
34 |
35 | # 原始地图数据, 从 maps 接口获取到的数据
36 | map_data_path = "./map_data.txt"
37 |
38 | # 随机种子,从 map_info_ex 接口"data"字段下的"map_seed"获取到的数据,默认种子为:seed = [0, 0, 0, 0]
39 | seed = [3270836840, 3431855579, 3015956679, 1737139174]
40 |
41 | """ 制作地图数据 """
42 |
43 | print("==========================================")
44 |
45 | # 判断原始地图数据文件是否存在
46 | if not isfile(map_data_path):
47 | input("原始地图数据文件不存在!")
48 | exit(1)
49 |
50 | # 读取原始地图数据
51 | map_data = json.loads(open(map_data_path).read())
52 |
53 | # 根据"blockTypeData"字段按顺序生成所有类型的方块,存放到数组
54 | block_type_data = map_data["blockTypeData"]
55 | block_types = []
56 | for i in range(1, 16+1):
57 | block_type = str(i)
58 | if block_type in block_type_data:
59 | count = block_type_data[block_type] * 3
60 | block_types.extend([i] * count)
61 |
62 | # 调用js方法将数组打乱,打乱后的结果和游戏的一样
63 | block_types = execjs.compile(js_code).call("shuffle", block_types, seed)
64 | print(block_types)
65 |
66 | # 将游戏的层数排序
67 | level_data = map_data["levelData"]
68 | layers = list(level_data.keys())
69 | layers.sort(key=lambda x:int(x))
70 |
71 | # 为了方便three.js按顺序读取层数,所以将层数保存起来
72 | map_data["layers"] = layers
73 |
74 | # 将打乱后的图案按顺序填充到每个方块的"type"字段里
75 | index = 0
76 | for layer in layers:
77 | for block_data in level_data[layer]:
78 | if block_data["type"] > 0:
79 | continue
80 | block_data["type"] = block_types[index]
81 | index += 1
82 |
83 | print("==========================================")
84 | # 保存关卡数据到文件
85 | with open("map_data.json", "w", encoding="utf8") as f:
86 | f.write(json.dumps(map_data, indent=4))
87 | print("已将当前关卡数据保存到当前路径下 map_data.json 文件!")
88 | # 同步进行自动求解
89 | if isfile("config.json"):
90 | try:
91 | with open("config.json","r",encoding="utf8") as f:
92 | configs = json.loads(f.read())
93 | if "issort" not in configs or "percent" not in configs or "timeout" not in configs or ("timeout" in configs and type(configs["timeout"]) != int) or ("percent" in configs and type(configs["percent"]) != float):
94 | print("\n当前配置文件存在错误,将使用默认配置求解!")
95 | configs = {"issort":"","percent":0.85,"timeout":60}
96 | with open("config.json","w",encoding="utf8") as f:
97 | f.write(json.dumps(configs,indent=4))
98 | else:
99 | print("\n将使用配置文件 config.json 的配置求解!")
100 | except:
101 | print("\n当前配置文件存在错误,将使用默认配置求解!")
102 | configs = {"issort":"","percent":0.85,"timeout":60}
103 | with open("config.json","w",encoding="utf8") as f:
104 | f.write(json.dumps(configs,indent=4))
105 | else:
106 | print("\n当前配置文件不存在,将使用默认配置求解!")
107 | configs = {"issort":"","percent":0.85,"timeout":60}
108 | with open("config.json","w",encoding="utf8") as f:
109 | f.write(json.dumps(configs,indent=4))
110 |
111 | issort = configs["issort"]
112 | percent = configs["percent"]
113 | timeout = configs["timeout"]
114 |
115 | if issort != "true" and issort != "reverse" and percent == 0.85:
116 | threadName = "普通模式"
117 | command1 = "python3 autoSolve.py -s reverse -t %d"%timeout
118 | command2 = "python3 autoSolve.py -p 0 -t %d"%timeout
119 | command3 = "python3 autoSolve.py -s reverse -p 0 -t %d"%timeout
120 | elif issort == "reverse" and percent == 0.85:
121 | threadName = "高层优先模式"
122 | command1 = "python3 autoSolve.py -t %d"%timeout
123 | command2 = "python3 autoSolve.py -p 0 -t %d"%timeout
124 | command3 = "python3 autoSolve.py -s reverse -p 0 -t %d"%timeout
125 | elif issort != "true" and issort != "reverse" and percent == 0:
126 | threadName = "优先移除两张相同类型的手牌模式"
127 | command1 = "python3 autoSolve.py -s reverse -t %d"%timeout
128 | command2 = "python3 autoSolve.py -t %d"%timeout
129 | command3 = "python3 autoSolve.py -s reverse -p 0 -t %d"%timeout
130 | elif issort == "reverse" and percent == 0:
131 | threadName = "高层优先且优先移除两张相同类型的手牌模式"
132 | command1 = "python3 autoSolve.py -s reverse -t %d"%timeout
133 | command2 = "python3 autoSolve.py -p 0 -t %d"%timeout
134 | command3 = "python3 autoSolve.py -t %d"%timeout
135 | else:
136 | threadName = "自定义模式"
137 | command1 = "python3 autoSolve.py -s reverse -t %d"%timeout
138 | command2 = "python3 autoSolve.py -p 0 -t %d"%timeout
139 | command3 = "python3 autoSolve.py -s reverse -p 0 -t %d"%timeout
140 | command4 = "python3 autoSolve.py -p 0 -t %d"%timeout
141 |
142 | try:
143 | _thread.start_new_thread( cmd, (command1,))
144 | _thread.start_new_thread( cmd, (command2,))
145 | _thread.start_new_thread( cmd, (command3,))
146 | if threadName == "自定义模式":
147 | _thread.start_new_thread( cmd, (command4,))
148 | except Exception as e:
149 | print ("Error: 无法启动线程\n%s"%e)
150 |
151 | #print("\n建议同时在新的命令行终端分别同时运行以下命令:\npython3 autoSolve.py -s reverse\npython3 autoSolve.py -p 0\npython3 autoSolve.py -s reverse -p 0\n")
152 | print("开始求解,请稍等%d秒..."%timeout)
153 | auto_solve(map_data, issort, percent, timeout, threadName)
--------------------------------------------------------------------------------
/business/SheepSolver.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import json
3 | #import os
4 | #import sys
5 | #from hepler.FileHelper import FileHelper
6 | from item.Card import Card
7 | from item.CardPosition import CardPosition
8 | from item.ResidualPool import ResidualPool
9 | #from func_timeout import func_set_timeout
10 |
11 |
12 | class SheepSolver(object):
13 | def __init__(self, map_data):
14 | self.map_data = map_data
15 | slove_map_data = {}
16 | for level, data_list in map_data["levelData"].items():
17 | slove_map_data[level] = []
18 | for data_item in data_list:
19 | slove_item = {"type": data_item["type"],
20 | "min_x": data_item["rolNum"],
21 | "min_y": data_item["rowNum"],
22 | "max_x": data_item["rolNum"] + 8,
23 | "max_y": data_item["rowNum"] + 8}
24 | slove_map_data[level].append(slove_item)
25 | self._origin_data = slove_map_data
26 | self._card_count = 0
27 | self._card_position = CardPosition()
28 | self._residual_pool = ResidualPool()
29 | self._pick_list = []
30 | self._situation_history = set()
31 | self.picked_list = []
32 |
33 | def init_card_data(self):
34 | self._origin_data = dict(sorted(self._origin_data.items(), key=lambda item: int(item[0])))
35 | for level, level_data in self._origin_data.items():
36 | self._card_count += len(level_data)
37 | card_list = [Card(item) for item in level_data]
38 | self._card_position.append_level_card(card_list)
39 | self._card_position.generate_head_data()
40 |
41 | #@func_set_timeout(300)
42 | def solve(self, issort, percent):
43 | #print("\r当前进度为: {}/{}".format(len(self._pick_list), self._card_count), end="")
44 | if (len(self._pick_list)/self._card_count) >= percent:
45 | pool_card = copy.deepcopy(self._residual_pool._pool_card)
46 | for i in pool_card.keys():
47 | if pool_card[i] == 2:
48 | if issort == "true":
49 | head_list = sorted(self._card_position.get_head_key_list())
50 | elif issort == "reverse":
51 | head_list = sorted(self._card_position.get_head_key_list(), reverse=True)
52 | else:
53 | head_list = self._card_position.get_head_key_list()
54 | for j in head_list:
55 | original_data = self._card_position.get_card_detail(j)._origin_data
56 | if original_data["type"] == i:
57 | self._operation_pick_card(j)
58 | head_fingerprint = self._card_position.get_head_description()
59 | if head_fingerprint in self._situation_history:
60 | self._operation_recover_card(j)
61 | continue
62 | else:
63 | self._situation_history.add(head_fingerprint)
64 | if self._residual_pool.is_pool_full():
65 | self._operation_recover_card(j)
66 | continue
67 | self.solve(issort, percent)
68 | if self.picked_list != []:
69 | return True
70 | if not self._card_position.is_head_data_empty():
71 | self._operation_recover_card(j)
72 | else:
73 | self.picked_list = self._pick_list
74 | return True
75 | break
76 | break
77 | if issort == "true":
78 | head_list = sorted(self._card_position.get_head_key_list())
79 | elif issort == "reverse":
80 | head_list = sorted(self._card_position.get_head_key_list(), reverse=True)
81 | else:
82 | head_list = self._card_position.get_head_key_list()
83 | for head_item in head_list:
84 | self._operation_pick_card(head_item)
85 | head_fingerprint = self._card_position.get_head_description()
86 | if head_fingerprint in self._situation_history:
87 | self._operation_recover_card(head_item)
88 | continue
89 | else:
90 | self._situation_history.add(head_fingerprint)
91 | if self._residual_pool.is_pool_full():
92 | self._operation_recover_card(head_item)
93 | continue
94 | self.solve(issort, percent)
95 | if self.picked_list != []:
96 | return True
97 | if not self._card_position.is_head_data_empty():
98 | self._operation_recover_card(head_item)
99 | else:
100 | self.picked_list = self._pick_list
101 | return True
102 |
103 | def test_result(self, pick_list: list):
104 | for pick_index in pick_list:
105 | self._operation_pick_card(pick_index)
106 | print(self._residual_pool.show_pool_state())
107 |
108 | def _operation_pick_card(self, card_index):
109 | self._card_position.pick_card(card_index)
110 | card_detail = self._card_position.get_card_detail(card_index)
111 | self._residual_pool.pick_card(card_detail)
112 | self._pick_list.append(card_index)
113 |
114 | def _operation_recover_card(self, card_index):
115 | self._card_position.recover_card(card_index)
116 | card_detail = self._card_position.get_card_detail(card_index)
117 | self._residual_pool.recover_card(card_detail)
118 | self._pick_list.remove(card_index)
119 |
120 | def print_result(self):
121 | if self.picked_list != []:
122 | print(json.dumps(self.picked_list))
123 | else:
124 | print("牌面无解")
125 |
126 | def get_result(self):
127 | if self.picked_list != []:
128 | operations = []
129 | for i in self.picked_list:
130 | count = 0
131 | for data_list in self.map_data["levelData"].values():
132 | for data_item in data_list:
133 | count += 1
134 | if count == i:
135 | operations.append(data_item["id"])
136 | break
137 | if count == i:
138 | break
139 | self.map_data["operations"] = operations
140 | return self.map_data
141 | else:
142 | return "牌面无解"
143 |
144 |
--------------------------------------------------------------------------------
/sheep.py:
--------------------------------------------------------------------------------
1 | from os.path import isfile
2 | from mitmproxy import ctx
3 | from autoSolve import auto_solve
4 | from subprocess import Popen, PIPE, STDOUT
5 | import execjs
6 | import json
7 | import _thread
8 | import sys
9 |
10 |
11 | def cmd(command):
12 | encode = "utf8"
13 | if sys.platform == "win32":
14 | encode = "gbk"
15 | subp = Popen(args=command, shell=True, encoding=encode, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
16 | subp.wait()
17 | if subp.poll() == 0:
18 | output = ""
19 | for i in (subp.communicate()[0]).split("\n"):
20 | if "进度" in i and output == "":
21 | output += "\n%s:\033[0m"%i[:i.index("进度")]
22 | elif "超时" in i:
23 | output += "\033[0;33;40m%s"%i[i.index("自动求解超时"):]
24 | elif "无解" in i:
25 | output += "\033[0;33;40m%s"%i[i.index("牌面无解"):]
26 | elif "计算用时" in i:
27 | output += "\033[0;32;40m%s | "%i[i.index("计算用时"):]
28 | elif "当前关卡3D地图地址" in i:
29 | output += "%s"%i
30 | elif "地图生成失败" in i:
31 | output += "%s"%i
32 | print(output)
33 | else:
34 | print("失败")
35 | print(subp.communicate()[0])
36 |
37 |
38 | class Sheep():
39 |
40 | def __init__(self):
41 | self.seed = [0, 0, 0, 0]
42 | self.js_code = open("shuffle.js", encoding="utf-8").read()
43 | self.map_data_path = "./map_data.txt"
44 | self.map_data_topic_path = "./map_data_topic.txt"
45 |
46 | def response(self, flow):
47 | """ 接口响应方法 """
48 | if "map_info_ex" in flow.request.path:
49 | # 获取随机种子的接口,随机种子存储到self.seed中
50 | response = json.loads(flow.response.content)
51 | self.seed = response["data"]["map_seed"]
52 | self.make_map_data(False)
53 | elif "topic/game_start" in flow.request.path:
54 | # 今日话题获取随机种子的接口
55 | response = json.loads(flow.response.content)
56 | self.seed = response["data"]["map_seed"]
57 | self.make_map_data(True)
58 | elif "maps" in flow.request.path:
59 | # 解析原始地图数据
60 | response = json.loads(flow.response.content)
61 | # 不解析第一关
62 | if response["levelKey"] < 90000:
63 | return
64 | # 判断是否是话题挑战
65 | is_topic = (response["levelKey"] >= 100000)
66 | # 保存原始地图数据
67 | map_data_path = self.get_map_data_path(is_topic)
68 | with open(map_data_path, "w") as f:
69 | f.write(json.dumps(response, indent=4))
70 | f.close()
71 | self.make_map_data(is_topic)
72 |
73 | def get_map_data_path(self, is_topic):
74 | """ 获取文件路径 """
75 | if is_topic:
76 | return self.map_data_topic_path
77 | else:
78 | return self.map_data_path
79 |
80 | def make_map_data(self, is_topic):
81 | """ 制作地图数据 """
82 |
83 | print("==========================================")
84 |
85 | # 判断原始地图文件是否存在
86 | map_data_path = self.get_map_data_path(is_topic)
87 | if not isfile(map_data_path):
88 | return
89 |
90 | # 读取原始地图数据
91 | map_data = json.loads(open(map_data_path).read())
92 |
93 | # 根据"blockTypeData"字段按顺序生成所有类型的方块,存放到数组
94 | block_type_data = map_data["blockTypeData"]
95 | block_types = []
96 | for i in range(1, 16+1):
97 | block_type = str(i)
98 | if block_type in block_type_data:
99 | count = block_type_data[block_type] * 3
100 | block_types.extend([i] * count)
101 |
102 | # 调用js方法将数组打乱,打乱后的结果和游戏的一样
103 | block_types = execjs.compile(self.js_code).call(
104 | "shuffle", block_types, self.seed)
105 | print(block_types)
106 |
107 | # 将游戏的层数排序
108 | level_data = map_data["levelData"]
109 | layers = list(level_data.keys())
110 | layers.sort(key=lambda x: int(x))
111 |
112 | # 为了方便three.js按顺序读取层数,所以将层数保存起来
113 | map_data["layers"] = layers
114 |
115 | # 将打乱后的图案按顺序填充到每个方块的"type"字段里
116 | index = 0
117 | for layer in layers:
118 | for block_data in level_data[layer]:
119 | if block_data["type"] > 0:
120 | continue
121 | block_data["type"] = block_types[index]
122 | index += 1
123 |
124 | print("==========================================")
125 | # 保存关卡数据到文件
126 | with open("map_data.json", "w", encoding="utf8") as f:
127 | f.write(json.dumps(map_data, indent=4))
128 | print("已将当前关卡数据保存到当前路径下 map_data.json 文件!")
129 | # 同步进行自动求解
130 | if isfile("config.json"):
131 | try:
132 | with open("config.json","r",encoding="utf8") as f:
133 | configs = json.loads(f.read())
134 | if "issort" not in configs or "percent" not in configs or "timeout" not in configs or ("timeout" in configs and type(configs["timeout"]) != int) or ("percent" in configs and type(configs["percent"]) != float):
135 | print("\n当前配置文件存在错误,将使用默认配置求解!")
136 | configs = {"issort":"","percent":0.85,"timeout":60}
137 | with open("config.json","w",encoding="utf8") as f:
138 | f.write(json.dumps(configs,indent=4))
139 | else:
140 | print("\n将使用配置文件 config.json 的配置求解!")
141 | except:
142 | print("\n当前配置文件存在错误,将使用默认配置求解!")
143 | configs = {"issort":"","percent":0.85,"timeout":60}
144 | with open("config.json","w",encoding="utf8") as f:
145 | f.write(json.dumps(configs,indent=4))
146 | else:
147 | print("\n当前配置文件不存在,将使用默认配置求解!")
148 | configs = {"issort":"","percent":0.85,"timeout":60}
149 | with open("config.json","w",encoding="utf8") as f:
150 | f.write(json.dumps(configs,indent=4))
151 |
152 | issort = configs["issort"]
153 | percent = configs["percent"]
154 | timeout = configs["timeout"]
155 |
156 | encode = "utf8"
157 | if sys.platform == "win32":
158 | encode = "gbk"
159 | python_cmd = "python3"
160 | subp = Popen(args="%s -V"%python_cmd, shell=True, encoding=encode, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
161 | subp.wait()
162 | if "Python" not in subp.communicate()[0]:
163 | python_cmd = "python"
164 |
165 | if issort != "true" and issort != "reverse" and percent == 0.85:
166 | threadName = "普通模式"
167 | command1 = "%s autoSolve.py -s reverse -t %d"%(python_cmd, timeout)
168 | command2 = "%s autoSolve.py -p 0 -t %d"%(python_cmd, timeout)
169 | command3 = "%s autoSolve.py -s reverse -p 0 -t %d"%(python_cmd, timeout)
170 | elif issort == "reverse" and percent == 0.85:
171 | threadName = "高层优先模式"
172 | command1 = "%s autoSolve.py -t %d"%(python_cmd, timeout)
173 | command2 = "%s autoSolve.py -p 0 -t %d"%(python_cmd, timeout)
174 | command3 = "%s autoSolve.py -s reverse -p 0 -t %d"%(python_cmd, timeout)
175 | elif issort != "true" and issort != "reverse" and percent == 0:
176 | threadName = "优先移除两张相同类型的手牌模式"
177 | command1 = "%s autoSolve.py -s reverse -t %d"%(python_cmd, timeout)
178 | command2 = "%s autoSolve.py -t %d"%(python_cmd, timeout)
179 | command3 = "%s autoSolve.py -s reverse -p 0 -t %d"%(python_cmd, timeout)
180 | elif issort == "reverse" and percent == 0:
181 | threadName = "高层优先且优先移除两张相同类型的手牌模式"
182 | command1 = "%s autoSolve.py -s reverse -t %d"%(python_cmd, timeout)
183 | command2 = "%s autoSolve.py -p 0 -t %d"%(python_cmd, timeout)
184 | command3 = "%s autoSolve.py -t %d"%(python_cmd, timeout)
185 | else:
186 | threadName = "自定义模式"
187 | command1 = "%s autoSolve.py -s reverse -t %d"%(python_cmd, timeout)
188 | command2 = "%s autoSolve.py -p 0 -t %d"%(python_cmd, timeout)
189 | command3 = "%s autoSolve.py -s reverse -p 0 -t %d"%(python_cmd, timeout)
190 | command4 = "%s autoSolve.py -p 0 -t %d"%(python_cmd, timeout)
191 |
192 | try:
193 | #print("\n建议同时在新的命令行终端分别同时运行以下命令:\npython3 autoSolve.py -s reverse\npython3 autoSolve.py -p 0\npython3 autoSolve.py -s reverse -p 0\n")
194 | print("开始求解,请稍等%d秒..."%timeout)
195 | _thread.start_new_thread( auto_solve, (map_data, issort, percent, timeout, threadName,) )
196 | _thread.start_new_thread( cmd, (command1,))
197 | _thread.start_new_thread( cmd, (command2,))
198 | _thread.start_new_thread( cmd, (command3,))
199 | if threadName == "自定义模式":
200 | _thread.start_new_thread( cmd, (command4,))
201 | except Exception as e:
202 | print ("Error: 无法启动线程\n%s"%e)
203 |
204 | addons = [Sheep()]
205 |
--------------------------------------------------------------------------------
/html/sheep_map/map_data.php:
--------------------------------------------------------------------------------
1 |
2 | open('../sheep_maps.db');
6 | }
7 | }
8 | $db = new MyDB();
9 | if(!$db){
10 | echo "window.alert('".$db->lastErrorMsg()."');\n";
11 | //echo $db->lastErrorMsg();
12 | } else {
13 | echo "console.log('成功打开数据文件');\n";
14 | //echo "成功创建或打开数据文件\n";
15 | }
16 | if(is_array($_GET)&&count($_GET)>0){//判断是否有Get参数
17 | if(isset($_GET["id"])){//判断所需要的参数是否存在,isset用来检测变量是否设置,返回true or false
18 | $id = $_GET["id"];//存在
19 | }
20 | }
21 | if(isset($id) == false){
22 | $ret1 = $db->query("SELECT MAX(ID),MAP_INFO from MAPS");
23 | while($row = $ret1->fetchArray()){
24 | $map_info = $row["MAP_INFO"];
25 | $id = $row["MAX(ID)"];
26 | echo "const map_data = $map_info;\n";
27 | }
28 | } else {
29 | $ret1 = $db->query("SELECT ID,MAP_INFO from MAPS WHERE ID = $id");
30 | while($row = $ret1->fetchArray()){
31 | $map_info = $row["MAP_INFO"];
32 | echo "const map_data = $map_info;\n";
33 | }
34 | if(isset($map_info) == false){
35 | echo "window.alert('没有查询到 id=$id 的关卡地图数据!关卡地图数据可能已过期或者id不正确!')\n";
36 | }
37 | }
38 | $ret2 = $db->query("SELECT MIN(ID) from MAPS");
39 | while($row = $ret2->fetchArray()){
40 | $min_id = $row["MIN(ID)"];
41 | if(($id - $min_id) >= 100){
42 | $ret3 = $db->exec("DELETE from MAPS where ID=$min_id;");
43 | if(!$ret3){
44 | echo "window.alert('".$db->lastErrorMsg()."');\n";
45 | } else {
46 | echo "console.log('".$db->changes()." 成功删除数据');\n";
47 | }
48 | }
49 | }
50 | ?>
51 |
52 | import * as THREE from 'three';
53 |
54 | import { OrbitControls } from 'OrbitControls';
55 |
56 | let camera, controls, scene, renderer;
57 | const raycaster = new THREE.Raycaster();
58 | const mouse = new THREE.Vector2();
59 | const removed_blocks = [];
60 |
61 | // 显示解答步骤的变量
62 | var block_objects = {}
63 | var solve_index = 0;
64 | var highlight_mesh = null;
65 | var solve_interval = null;
66 |
67 | var material_blocks = [];
68 | var mask_material_blocks = [];
69 | var material_side;
70 |
71 | // 卡槽
72 | var slots = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
73 | var counter = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
74 | var slot_objects = [];
75 |
76 | init();
77 | //render(); // remove when using next line for animation loop (requestAnimationFrame)
78 | animate();
79 |
80 | bindEvent();
81 |
82 | function init() {
83 |
84 | scene = new THREE.Scene();
85 | scene.background = new THREE.Color( 0xcff998 );
86 | //scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 );
87 |
88 | renderer = new THREE.WebGLRenderer( { antialias: true } );
89 | renderer.setPixelRatio( window.devicePixelRatio );
90 | renderer.setSize( window.innerWidth, window.innerHeight );
91 | document.body.appendChild( renderer.domElement );
92 |
93 | //camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 1, 2000 );
94 | camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 2000 );
95 | camera.zoom = 7;
96 | camera.setViewOffset( window.innerWidth, window.innerHeight, 0, -200, window.innerWidth, window.innerHeight );
97 | camera.position.set( 0, 0, 0 );
98 |
99 | // controls
100 |
101 | controls = new OrbitControls( camera, renderer.domElement );
102 | controls.listenToKeyEvents( window ); // optional
103 |
104 | //controls.addEventListener( 'change', render ); // call this only in static scenes (i.e., if there is no animation loop)
105 |
106 | controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
107 | controls.dampingFactor = 0.05;
108 |
109 | controls.screenSpacePanning = false;
110 |
111 | controls.minDistance = 100;
112 | controls.maxDistance = 500;
113 |
114 | controls.maxPolarAngle = Math.PI / 2;
115 |
116 | // 构建地图遮挡关系
117 | var mask_data = [];
118 | for (var row = 0; row < 80; row++) {
119 | var rows = [];
120 | for (var col = 0; col < 64; col++) {
121 | rows.push(null);
122 | }
123 | mask_data.push(rows);
124 | }
125 | const layers = map_data['layers'];
126 | const level_data = map_data['levelData'];
127 | for (let i = 0; i < layers.length; i++) {
128 | var layer = layers[i];
129 | var block_datas = level_data[layer];
130 | for (let j = 0; j < block_datas.length; j++) {
131 | var block_data = block_datas[j];
132 | counter[block_data.type] += 1;
133 | block_data.pre_blocks = []; // 遮挡住的方块
134 | block_data.next_blocks = []; // 被遮挡的方块
135 | // 取走方块方法
136 | block_data.take_away = function() {
137 | for (var i = 0; i < this.pre_blocks.length; i++) {
138 | var pre_block = this.pre_blocks[i];
139 | pre_block.next_blocks.pop(this);
140 | update_block_material(block_objects[pre_block.id]);
141 | }
142 | counter[this.type] -= 1;
143 | slots[this.type] += 1;
144 | if (slots[this.type] >= 3) {
145 | slots[this.type] = 0;
146 | }
147 | update_slots();
148 | }
149 | // 放回方块方法
150 | block_data.put_back = function() {
151 | for (var i = 0; i < this.pre_blocks.length; i++) {
152 | var pre_block = this.pre_blocks[i];
153 | pre_block.next_blocks.push(this);
154 | update_block_material(block_objects[pre_block.id]);
155 | }
156 | counter[this.type] += 1;
157 | slots[this.type] -= 1;
158 | if (slots[this.type] < 0) {
159 | slots[this.type] = 2;
160 | }
161 | update_slots();
162 | }
163 | // 是否可以移除
164 | block_data.removable = function() {
165 | return this.next_blocks.length == 0;
166 | }
167 | // 找出被当前方块遮挡住的方块
168 | var pre_blocks = [];
169 | for (var col = block_data.rolNum; col < block_data.rolNum+8; col++) {
170 | for (var row = block_data.rowNum; row < block_data.rowNum+8; row++) {
171 | var pre_block = mask_data[row][col];
172 | if (pre_block) {
173 | pre_blocks.push(pre_block);
174 | }
175 | mask_data[row][col] = block_data;
176 | }
177 | }
178 | // 构建方块的遮挡关系
179 | for (var k = 0; k < pre_blocks.length; k++) {
180 | var pre_block = pre_blocks[k];
181 | if (block_data.pre_blocks.indexOf(pre_block) < 0) {
182 | block_data.pre_blocks.push(pre_block);
183 | }
184 | if (pre_block.next_blocks.indexOf(block_data) < 0) {
185 | pre_block.next_blocks.push(block_data);
186 | }
187 | }
188 | }
189 | }
190 | //console.log(mask_data);
191 |
192 | // 方块图案
193 | const textureLoader = new THREE.TextureLoader();
194 | material_side = new THREE.MeshLambertMaterial({
195 | map: textureLoader.load('images/side.png'),
196 | })
197 | for (let i = 0; i <= 16; i++) {
198 | material_blocks.push(new THREE.MeshLambertMaterial({
199 | map: textureLoader.load(`images/${i}.png`),
200 | }));
201 | mask_material_blocks.push(new THREE.MeshLambertMaterial({
202 | map: textureLoader.load(`images/mask/${i}.png`),
203 | }));
204 | }
205 |
206 | // 创建方块
207 | var geometry = new THREE.BoxGeometry(8, 2, 8);
208 | for (let i = 0; i < layers.length; i++) {
209 | var layer = layers[i];
210 | var block_datas = level_data[layer];
211 | for (let j = 0; j < block_datas.length; j++) {
212 | var block_data = block_datas[j];
213 | print_block_info(block_data, false);
214 | const block_object = new THREE.Mesh(geometry, null);
215 | block_object.position.x = block_data['rolNum'] - 28;
216 | block_object.position.y = (block_data['layerNum'] - 1) * 3.5;
217 | block_object.position.z = block_data['rowNum'] - 36;
218 | block_object.updateMatrix();
219 | block_object.matrixAutoUpdate = false;
220 | block_object.block_data = block_data;
221 | scene.add(block_object);
222 | block_objects[block_data['id']] = block_object;
223 | update_block_material(block_object);
224 | }
225 | }
226 |
227 | // 卡槽方块
228 | for (let i = 0; i < 7; i++) {
229 | const block_object = new THREE.Mesh(geometry, null);
230 | block_object.position.x = 8 * i - 24;
231 | block_object.position.y = 0;
232 | block_object.position.z = -64;
233 | block_object.updateMatrix();
234 | block_object.matrixAutoUpdate = false;
235 | scene.add(block_object);
236 | slot_objects.push(block_object);
237 | var block_data = {
238 | "type" : 0,
239 | "pre_blocks" : [],
240 | "next_blocks" : [],
241 | "is_slot" : true,
242 | }
243 | block_data.removable = function() {
244 | return true;
245 | }
246 | block_object.block_data = block_data;
247 | update_block_material(block_object);
248 | }
249 |
250 | if (map_data['operations'] != null) {
251 |
252 | // 高亮指示器
253 | geometry = new THREE.BoxGeometry(8, 2, 8);
254 | const material = new THREE.MeshBasicMaterial({color:0xff0000, opacity:0.6, transparent:true})
255 | highlight_mesh = new THREE.Mesh(geometry, material);
256 | highlight_mesh.position.x = 1000;
257 | highlight_mesh.position.y = 1000;
258 | highlight_mesh.position.z = 1000;
259 | highlight_mesh.updateMatrix();
260 | highlight_mesh.matrixAutoUpdate = false;
261 | scene.add(highlight_mesh);
262 | update_highlight_mesh();
263 |
264 | document.getElementById('auto_solve').text = "【自动解答】";
265 | document.getElementById('single_step_solve').text = "【单步解答】";
266 | }
267 |
268 | // lights
269 | const dirLight0 = new THREE.DirectionalLight( 0xffffff );
270 | dirLight0.position.set( 0, 100, 0 );
271 | scene.add( dirLight0 );
272 |
273 | const dirLight1 = new THREE.DirectionalLight( 0xffffff );
274 | dirLight1.position.set( 1, 0, 1 );
275 | scene.add( dirLight1 );
276 |
277 | const dirLight2 = new THREE.DirectionalLight( 0xffffff );
278 | dirLight2.position.set( - 1, - 1, - 1 );
279 | scene.add( dirLight2 );
280 |
281 | const ambientLight = new THREE.AmbientLight( 0x222222 );
282 | scene.add( ambientLight );
283 |
284 | window.addEventListener( 'resize', onWindowResize );
285 |
286 | document.addEventListener( 'click', onMouseClick );
287 | }
288 |
289 | function onWindowResize() {
290 | camera.aspect = window.innerWidth / window.innerHeight;
291 | camera.updateProjectionMatrix();
292 | renderer.setSize( window.innerWidth, window.innerHeight );
293 | }
294 |
295 | function onMouseClick(event) {
296 |
297 | //将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标
298 | mouse.x = (event.clientX/window.innerWidth) * 2 - 1;
299 | mouse.y = -((event.clientY/window.innerHeight) * 2 - 1);
300 |
301 | // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
302 | raycaster.setFromCamera( mouse, camera );
303 |
304 | // 获取raycaster直线和所有模型相交的数组集合
305 | var intersects = raycaster.intersectObjects( scene.children );
306 | //console.log(intersects);
307 |
308 | if (intersects.length > 0) {
309 | var object = intersects[0].object;
310 | var block_data = object.block_data;
311 | if (!block_data.removable()) {
312 | return;
313 | }
314 | if (block_data.is_slot) {
315 | return;
316 | }
317 | if (map_data['operations'] != null) {
318 | alert("有解的情况禁止手动移除方块,不然把解答途中的方块移除掉会导致局面出现问题。");
319 | return;
320 | }
321 | if (is_game_over()) {
322 | return;
323 | }
324 | print_block_info(block_data, true);
325 | removed_blocks.push(object);
326 | scene.remove(object);
327 | block_data.take_away();
328 | }
329 | }
330 |
331 | function animate() {
332 | requestAnimationFrame( animate );
333 | controls.update(); // only required if controls.enableDamping = true, or if controls.autoRotate = true
334 | render();
335 | }
336 |
337 | function render() {
338 | renderer.render( scene, camera );
339 | }
340 |
341 | // 打印方块信息
342 | function print_block_info(block_data, is_remove) {
343 |
344 | var type2name = {
345 | 1: "青草",
346 | 2: "胡萝卜",
347 | 3: "玉米",
348 | 4: "树桩",
349 | 5: "草叉",
350 | 6: "白菜",
351 | 7: "羊毛",
352 | 8: "刷子",
353 | 9: "剪刀",
354 | 10: "奶瓶",
355 | 11: "水桶",
356 | 12: "手套",
357 | 13: "铃铛",
358 | 14: "火堆",
359 | 15: "毛球",
360 | 16: "干草"
361 | }
362 |
363 | var layer = block_data['layerNum'];
364 | var x = block_data['rolNum'];
365 | var y = block_data['rowNum'];
366 | var type = block_data['type'];
367 | var name = type2name[type];
368 | var info = `层数:${layer}, 坐标:(${x}, ${y}), 类型:${type}(${name})`
369 | if (is_remove) {
370 | info = "移除方块 >> " + info;
371 | }
372 | console.log(info);
373 | }
374 |
375 | // 游戏是否结束
376 | function is_game_over() {
377 | var sum = 0;
378 | for (var i = 0; i < slots.length; i++) {
379 | sum += slots[i];
380 | }
381 | return sum >= 7;
382 | }
383 |
384 | // 更新方块图案
385 | function update_block_material(block_object) {
386 | var material = null;
387 | var block_data = block_object.block_data;
388 | if (block_data.removable()) {
389 | material = material_blocks[block_data.type];
390 | } else {
391 | material = mask_material_blocks[block_data.type];
392 | }
393 | var materials = block_object.material;
394 | if (materials == null) {
395 | materials = [material_side, material_side, material, material_side, material_side, material_side];
396 | } else {
397 | materials[2] = material;
398 | }
399 | block_object.material = materials;
400 | }
401 |
402 | // 更新卡槽方块
403 | function update_slots() {
404 | for (let i = 0; i < 7; i++) {
405 | var object = slot_objects[i];
406 | object.block_data.type = 0;
407 | update_block_material(object);
408 | }
409 |
410 | var index = 0;
411 | for (let i = 0; i < slots.length; i++) {
412 | for (let j = 0; j < slots[i]; j++) {
413 | if (index >= 7) {
414 | return;
415 | }
416 | var object = slot_objects[index];
417 | object.block_data.type = i;
418 | update_block_material(object);
419 | index += 1;
420 | }
421 | }
422 | }
423 |
424 | // 更新高亮方块位置
425 | function update_highlight_mesh() {
426 | if (solve_index < map_data['operations'].length) {
427 | var block_id = map_data['operations'][solve_index];
428 | var block_object = block_objects[block_id];
429 | highlight_mesh.position.x = block_object.position.x;
430 | highlight_mesh.position.y = block_object.position.y;
431 | highlight_mesh.position.z = block_object.position.z;
432 | } else {
433 | highlight_mesh.position.x = 1000;
434 | highlight_mesh.position.y = 1000;
435 | highlight_mesh.position.z = 1000;
436 | }
437 | highlight_mesh.updateMatrix();
438 | }
439 |
440 | // 撤销移除
441 | function undo() {
442 | const object = removed_blocks.pop();
443 | if (object) {
444 | scene.add(object);
445 | object.block_data.put_back();
446 | if (solve_index > 0) {
447 | solve_index -= 1;
448 | }
449 | update_highlight_mesh();
450 | }
451 | }
452 |
453 | // 自动解答
454 | function auto_solve() {
455 | var auto_solve_element = document.getElementById('auto_solve');
456 | if (solve_interval == null) {
457 | solve_interval = setInterval(function() {
458 | single_step_solve();
459 | }, 1500);
460 | auto_solve_element.text = '【停止解答】';
461 | } else {
462 | clearInterval(solve_interval);
463 | solve_interval = null;
464 | auto_solve_element.text = '【自动解答】';
465 | }
466 | }
467 |
468 | // 单步解答
469 | function single_step_solve() {
470 | if (map_data['operations'] == null) {
471 | return;
472 | }
473 | if (solve_index >= map_data['operations'].length) {
474 | return;
475 | }
476 | var block_id = map_data['operations'][solve_index];
477 | var block_object = block_objects[block_id];
478 | scene.remove(block_object);
479 | removed_blocks.push(block_object);
480 | print_block_info(block_object.block_data, true);
481 | block_object.block_data.take_away();
482 | solve_index += 1;
483 | update_highlight_mesh();
484 | //console.log("counts :", counter);
485 | //console.log("slots :", slots);
486 | }
487 |
488 | function bindEvent(){
489 | document.getElementById('undo').onclick = undo;
490 | document.getElementById('auto_solve').onclick = auto_solve;
491 | document.getElementById('single_step_solve').onclick = single_step_solve;
492 | }
493 |
--------------------------------------------------------------------------------
/html/sheep_map/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 羊了个羊3D地图
5 |
6 |
7 |
39 |
40 |
41 |
42 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
61 |
62 |
507 |
508 |
509 |
--------------------------------------------------------------------------------
/html/sheep_map/map_data.js:
--------------------------------------------------------------------------------
1 | const map_data = {
2 | "widthNum": 8,
3 | "heightNum": 10,
4 | "levelKey": 90029,
5 | "blockTypeData": {
6 | "1": 6,
7 | "2": 6,
8 | "3": 6,
9 | "4": 6,
10 | "5": 5,
11 | "6": 5,
12 | "7": 5,
13 | "8": 5,
14 | "9": 5,
15 | "10": 5,
16 | "11": 5,
17 | "12": 5,
18 | "13": 5,
19 | "14": 5
20 | },
21 | "levelData": {
22 | "1": [
23 | {
24 | "id": "1-24-8",
25 | "type": 6,
26 | "rolNum": 24,
27 | "rowNum": 8,
28 | "layerNum": 1,
29 | "moldType": 1,
30 | "blockNode": null
31 | },
32 | {
33 | "id": "1-32-16",
34 | "type": 4,
35 | "rolNum": 32,
36 | "rowNum": 16,
37 | "layerNum": 1,
38 | "moldType": 1,
39 | "blockNode": null
40 | },
41 | {
42 | "id": "1-16-28",
43 | "type": 1,
44 | "rolNum": 16,
45 | "rowNum": 28,
46 | "layerNum": 1,
47 | "moldType": 1,
48 | "blockNode": null
49 | },
50 | {
51 | "id": "1-8-36",
52 | "type": 2,
53 | "rolNum": 8,
54 | "rowNum": 36,
55 | "layerNum": 1,
56 | "moldType": 1,
57 | "blockNode": null
58 | },
59 | {
60 | "id": "1-48-28",
61 | "type": 5,
62 | "rolNum": 48,
63 | "rowNum": 28,
64 | "layerNum": 1,
65 | "moldType": 1,
66 | "blockNode": null
67 | },
68 | {
69 | "id": "1-40-36",
70 | "type": 6,
71 | "rolNum": 40,
72 | "rowNum": 36,
73 | "layerNum": 1,
74 | "moldType": 1,
75 | "blockNode": null
76 | },
77 | {
78 | "id": "1-4-4",
79 | "type": 5,
80 | "rolNum": 4,
81 | "rowNum": 4,
82 | "layerNum": 1,
83 | "moldType": 1,
84 | "blockNode": null
85 | },
86 | {
87 | "id": "1-12-4",
88 | "type": 12,
89 | "rolNum": 12,
90 | "rowNum": 4,
91 | "layerNum": 1,
92 | "moldType": 1,
93 | "blockNode": null
94 | },
95 | {
96 | "id": "1-4-12",
97 | "type": 10,
98 | "rolNum": 4,
99 | "rowNum": 12,
100 | "layerNum": 1,
101 | "moldType": 1,
102 | "blockNode": null
103 | },
104 | {
105 | "id": "1-12-12",
106 | "type": 6,
107 | "rolNum": 12,
108 | "rowNum": 12,
109 | "layerNum": 1,
110 | "moldType": 1,
111 | "blockNode": null
112 | },
113 | {
114 | "id": "1-52-4",
115 | "type": 9,
116 | "rolNum": 52,
117 | "rowNum": 4,
118 | "layerNum": 1,
119 | "moldType": 1,
120 | "blockNode": null
121 | },
122 | {
123 | "id": "1-44-4",
124 | "type": 6,
125 | "rolNum": 44,
126 | "rowNum": 4,
127 | "layerNum": 1,
128 | "moldType": 1,
129 | "blockNode": null
130 | },
131 | {
132 | "id": "1-44-12",
133 | "type": 11,
134 | "rolNum": 44,
135 | "rowNum": 12,
136 | "layerNum": 1,
137 | "moldType": 1,
138 | "blockNode": null
139 | },
140 | {
141 | "id": "1-52-12",
142 | "type": 1,
143 | "rolNum": 52,
144 | "rowNum": 12,
145 | "layerNum": 1,
146 | "moldType": 1,
147 | "blockNode": null
148 | },
149 | {
150 | "id": "1-24-0",
151 | "type": 12,
152 | "rolNum": 24,
153 | "rowNum": 0,
154 | "layerNum": 1,
155 | "moldType": 1,
156 | "blockNode": null
157 | },
158 | {
159 | "id": "1-32-0",
160 | "type": 11,
161 | "rolNum": 32,
162 | "rowNum": 0,
163 | "layerNum": 1,
164 | "moldType": 1,
165 | "blockNode": null
166 | },
167 | {
168 | "id": "1-24-40",
169 | "type": 13,
170 | "rolNum": 24,
171 | "rowNum": 40,
172 | "layerNum": 1,
173 | "moldType": 1,
174 | "blockNode": null
175 | },
176 | {
177 | "id": "1-32-40",
178 | "type": 13,
179 | "rolNum": 32,
180 | "rowNum": 40,
181 | "layerNum": 1,
182 | "moldType": 1,
183 | "blockNode": null
184 | },
185 | {
186 | "id": "1-12-20",
187 | "type": 13,
188 | "rolNum": 12,
189 | "rowNum": 20,
190 | "layerNum": 1,
191 | "moldType": 1,
192 | "blockNode": null
193 | },
194 | {
195 | "id": "1-44-20",
196 | "type": 2,
197 | "rolNum": 44,
198 | "rowNum": 20,
199 | "layerNum": 1,
200 | "moldType": 1,
201 | "blockNode": null
202 | },
203 | {
204 | "id": "1-4-52",
205 | "type": 9,
206 | "rolNum": 4,
207 | "rowNum": 52,
208 | "layerNum": 1,
209 | "moldType": 2,
210 | "blockNode": null
211 | },
212 | {
213 | "id": "1-52-52",
214 | "type": 2,
215 | "rolNum": 52,
216 | "rowNum": 52,
217 | "layerNum": 1,
218 | "moldType": 2,
219 | "blockNode": null
220 | }
221 | ],
222 | "2": [
223 | {
224 | "id": "2-24-12",
225 | "type": 12,
226 | "rolNum": 24,
227 | "rowNum": 12,
228 | "layerNum": 2,
229 | "moldType": 1,
230 | "blockNode": null
231 | },
232 | {
233 | "id": "2-32-12",
234 | "type": 3,
235 | "rolNum": 32,
236 | "rowNum": 12,
237 | "layerNum": 2,
238 | "moldType": 1,
239 | "blockNode": null
240 | },
241 | {
242 | "id": "2-12-28",
243 | "type": 13,
244 | "rolNum": 12,
245 | "rowNum": 28,
246 | "layerNum": 2,
247 | "moldType": 1,
248 | "blockNode": null
249 | },
250 | {
251 | "id": "2-12-36",
252 | "type": 13,
253 | "rolNum": 12,
254 | "rowNum": 36,
255 | "layerNum": 2,
256 | "moldType": 1,
257 | "blockNode": null
258 | },
259 | {
260 | "id": "2-44-28",
261 | "type": 14,
262 | "rolNum": 44,
263 | "rowNum": 28,
264 | "layerNum": 2,
265 | "moldType": 1,
266 | "blockNode": null
267 | },
268 | {
269 | "id": "2-44-36",
270 | "type": 2,
271 | "rolNum": 44,
272 | "rowNum": 36,
273 | "layerNum": 2,
274 | "moldType": 1,
275 | "blockNode": null
276 | },
277 | {
278 | "id": "2-8-0",
279 | "type": 9,
280 | "rolNum": 8,
281 | "rowNum": 0,
282 | "layerNum": 2,
283 | "moldType": 1,
284 | "blockNode": null
285 | },
286 | {
287 | "id": "2-48-0",
288 | "type": 7,
289 | "rolNum": 48,
290 | "rowNum": 0,
291 | "layerNum": 2,
292 | "moldType": 1,
293 | "blockNode": null
294 | },
295 | {
296 | "id": "2-16-0",
297 | "type": 1,
298 | "rolNum": 16,
299 | "rowNum": 0,
300 | "layerNum": 2,
301 | "moldType": 1,
302 | "blockNode": null
303 | },
304 | {
305 | "id": "2-40-0",
306 | "type": 4,
307 | "rolNum": 40,
308 | "rowNum": 0,
309 | "layerNum": 2,
310 | "moldType": 1,
311 | "blockNode": null
312 | },
313 | {
314 | "id": "2-8-8",
315 | "type": 7,
316 | "rolNum": 8,
317 | "rowNum": 8,
318 | "layerNum": 2,
319 | "moldType": 1,
320 | "blockNode": null
321 | },
322 | {
323 | "id": "2-48-8",
324 | "type": 2,
325 | "rolNum": 48,
326 | "rowNum": 8,
327 | "layerNum": 2,
328 | "moldType": 1,
329 | "blockNode": null
330 | },
331 | {
332 | "id": "2-28-0",
333 | "type": 1,
334 | "rolNum": 28,
335 | "rowNum": 0,
336 | "layerNum": 2,
337 | "moldType": 1,
338 | "blockNode": null
339 | },
340 | {
341 | "id": "2-28-40",
342 | "type": 3,
343 | "rolNum": 28,
344 | "rowNum": 40,
345 | "layerNum": 2,
346 | "moldType": 1,
347 | "blockNode": null
348 | },
349 | {
350 | "id": "2-5-52",
351 | "type": 11,
352 | "rolNum": 5,
353 | "rowNum": 52,
354 | "layerNum": 2,
355 | "moldType": 2,
356 | "blockNode": null
357 | },
358 | {
359 | "id": "2-51-52",
360 | "type": 12,
361 | "rolNum": 51,
362 | "rowNum": 52,
363 | "layerNum": 2,
364 | "moldType": 2,
365 | "blockNode": null
366 | }
367 | ],
368 | "3": [
369 | {
370 | "id": "3-24-16",
371 | "type": 5,
372 | "rolNum": 24,
373 | "rowNum": 16,
374 | "layerNum": 3,
375 | "moldType": 1,
376 | "blockNode": null
377 | },
378 | {
379 | "id": "3-32-8",
380 | "type": 8,
381 | "rolNum": 32,
382 | "rowNum": 8,
383 | "layerNum": 3,
384 | "moldType": 1,
385 | "blockNode": null
386 | },
387 | {
388 | "id": "3-8-28",
389 | "type": 3,
390 | "rolNum": 8,
391 | "rowNum": 28,
392 | "layerNum": 3,
393 | "moldType": 1,
394 | "blockNode": null
395 | },
396 | {
397 | "id": "3-16-36",
398 | "type": 6,
399 | "rolNum": 16,
400 | "rowNum": 36,
401 | "layerNum": 3,
402 | "moldType": 1,
403 | "blockNode": null
404 | },
405 | {
406 | "id": "3-40-28",
407 | "type": 14,
408 | "rolNum": 40,
409 | "rowNum": 28,
410 | "layerNum": 3,
411 | "moldType": 1,
412 | "blockNode": null
413 | },
414 | {
415 | "id": "3-48-36",
416 | "type": 11,
417 | "rolNum": 48,
418 | "rowNum": 36,
419 | "layerNum": 3,
420 | "moldType": 1,
421 | "blockNode": null
422 | },
423 | {
424 | "id": "3-4-4",
425 | "type": 3,
426 | "rolNum": 4,
427 | "rowNum": 4,
428 | "layerNum": 3,
429 | "moldType": 1,
430 | "blockNode": null
431 | },
432 | {
433 | "id": "3-12-4",
434 | "type": 6,
435 | "rolNum": 12,
436 | "rowNum": 4,
437 | "layerNum": 3,
438 | "moldType": 1,
439 | "blockNode": null
440 | },
441 | {
442 | "id": "3-4-12",
443 | "type": 13,
444 | "rolNum": 4,
445 | "rowNum": 12,
446 | "layerNum": 3,
447 | "moldType": 1,
448 | "blockNode": null
449 | },
450 | {
451 | "id": "3-12-12",
452 | "type": 8,
453 | "rolNum": 12,
454 | "rowNum": 12,
455 | "layerNum": 3,
456 | "moldType": 1,
457 | "blockNode": null
458 | },
459 | {
460 | "id": "3-44-4",
461 | "type": 4,
462 | "rolNum": 44,
463 | "rowNum": 4,
464 | "layerNum": 3,
465 | "moldType": 1,
466 | "blockNode": null
467 | },
468 | {
469 | "id": "3-52-4",
470 | "type": 10,
471 | "rolNum": 52,
472 | "rowNum": 4,
473 | "layerNum": 3,
474 | "moldType": 1,
475 | "blockNode": null
476 | },
477 | {
478 | "id": "3-44-12",
479 | "type": 3,
480 | "rolNum": 44,
481 | "rowNum": 12,
482 | "layerNum": 3,
483 | "moldType": 1,
484 | "blockNode": null
485 | },
486 | {
487 | "id": "3-52-12",
488 | "type": 7,
489 | "rolNum": 52,
490 | "rowNum": 12,
491 | "layerNum": 3,
492 | "moldType": 1,
493 | "blockNode": null
494 | },
495 | {
496 | "id": "3-6-52",
497 | "type": 14,
498 | "rolNum": 6,
499 | "rowNum": 52,
500 | "layerNum": 3,
501 | "moldType": 2,
502 | "blockNode": null
503 | },
504 | {
505 | "id": "3-50-52",
506 | "type": 4,
507 | "rolNum": 50,
508 | "rowNum": 52,
509 | "layerNum": 3,
510 | "moldType": 2,
511 | "blockNode": null
512 | }
513 | ],
514 | "4": [
515 | {
516 | "id": "4-28-12",
517 | "type": 14,
518 | "rolNum": 28,
519 | "rowNum": 12,
520 | "layerNum": 4,
521 | "moldType": 1,
522 | "blockNode": null
523 | },
524 | {
525 | "id": "4-12-32",
526 | "type": 4,
527 | "rolNum": 12,
528 | "rowNum": 32,
529 | "layerNum": 4,
530 | "moldType": 1,
531 | "blockNode": null
532 | },
533 | {
534 | "id": "4-44-32",
535 | "type": 8,
536 | "rolNum": 44,
537 | "rowNum": 32,
538 | "layerNum": 4,
539 | "moldType": 1,
540 | "blockNode": null
541 | },
542 | {
543 | "id": "4-4-0",
544 | "type": 3,
545 | "rolNum": 4,
546 | "rowNum": 0,
547 | "layerNum": 4,
548 | "moldType": 1,
549 | "blockNode": null
550 | },
551 | {
552 | "id": "4-4-8",
553 | "type": 4,
554 | "rolNum": 4,
555 | "rowNum": 8,
556 | "layerNum": 4,
557 | "moldType": 1,
558 | "blockNode": null
559 | },
560 | {
561 | "id": "4-4-16",
562 | "type": 12,
563 | "rolNum": 4,
564 | "rowNum": 16,
565 | "layerNum": 4,
566 | "moldType": 1,
567 | "blockNode": null
568 | },
569 | {
570 | "id": "4-52-0",
571 | "type": 11,
572 | "rolNum": 52,
573 | "rowNum": 0,
574 | "layerNum": 4,
575 | "moldType": 1,
576 | "blockNode": null
577 | },
578 | {
579 | "id": "4-52-8",
580 | "type": 13,
581 | "rolNum": 52,
582 | "rowNum": 8,
583 | "layerNum": 4,
584 | "moldType": 1,
585 | "blockNode": null
586 | },
587 | {
588 | "id": "4-52-16",
589 | "type": 6,
590 | "rolNum": 52,
591 | "rowNum": 16,
592 | "layerNum": 4,
593 | "moldType": 1,
594 | "blockNode": null
595 | },
596 | {
597 | "id": "4-7-52",
598 | "type": 1,
599 | "rolNum": 7,
600 | "rowNum": 52,
601 | "layerNum": 4,
602 | "moldType": 2,
603 | "blockNode": null
604 | },
605 | {
606 | "id": "4-49-52",
607 | "type": 12,
608 | "rolNum": 49,
609 | "rowNum": 52,
610 | "layerNum": 4,
611 | "moldType": 2,
612 | "blockNode": null
613 | }
614 | ],
615 | "5": [
616 | {
617 | "id": "5-24-8",
618 | "type": 11,
619 | "rolNum": 24,
620 | "rowNum": 8,
621 | "layerNum": 5,
622 | "moldType": 1,
623 | "blockNode": null
624 | },
625 | {
626 | "id": "5-32-16",
627 | "type": 5,
628 | "rolNum": 32,
629 | "rowNum": 16,
630 | "layerNum": 5,
631 | "moldType": 1,
632 | "blockNode": null
633 | },
634 | {
635 | "id": "5-16-28",
636 | "type": 3,
637 | "rolNum": 16,
638 | "rowNum": 28,
639 | "layerNum": 5,
640 | "moldType": 1,
641 | "blockNode": null
642 | },
643 | {
644 | "id": "5-8-36",
645 | "type": 9,
646 | "rolNum": 8,
647 | "rowNum": 36,
648 | "layerNum": 5,
649 | "moldType": 1,
650 | "blockNode": null
651 | },
652 | {
653 | "id": "5-48-28",
654 | "type": 5,
655 | "rolNum": 48,
656 | "rowNum": 28,
657 | "layerNum": 5,
658 | "moldType": 1,
659 | "blockNode": null
660 | },
661 | {
662 | "id": "5-40-36",
663 | "type": 1,
664 | "rolNum": 40,
665 | "rowNum": 36,
666 | "layerNum": 5,
667 | "moldType": 1,
668 | "blockNode": null
669 | },
670 | {
671 | "id": "5-8-8",
672 | "type": 1,
673 | "rolNum": 8,
674 | "rowNum": 8,
675 | "layerNum": 5,
676 | "moldType": 1,
677 | "blockNode": null
678 | },
679 | {
680 | "id": "5-8-16",
681 | "type": 2,
682 | "rolNum": 8,
683 | "rowNum": 16,
684 | "layerNum": 5,
685 | "moldType": 1,
686 | "blockNode": null
687 | },
688 | {
689 | "id": "5-48-8",
690 | "type": 4,
691 | "rolNum": 48,
692 | "rowNum": 8,
693 | "layerNum": 5,
694 | "moldType": 1,
695 | "blockNode": null
696 | },
697 | {
698 | "id": "5-48-16",
699 | "type": 6,
700 | "rolNum": 48,
701 | "rowNum": 16,
702 | "layerNum": 5,
703 | "moldType": 1,
704 | "blockNode": null
705 | },
706 | {
707 | "id": "5-8-52",
708 | "type": 6,
709 | "rolNum": 8,
710 | "rowNum": 52,
711 | "layerNum": 5,
712 | "moldType": 2,
713 | "blockNode": null
714 | },
715 | {
716 | "id": "5-48-52",
717 | "type": 9,
718 | "rolNum": 48,
719 | "rowNum": 52,
720 | "layerNum": 5,
721 | "moldType": 2,
722 | "blockNode": null
723 | }
724 | ],
725 | "6": [
726 | {
727 | "id": "6-24-12",
728 | "type": 1,
729 | "rolNum": 24,
730 | "rowNum": 12,
731 | "layerNum": 6,
732 | "moldType": 1,
733 | "blockNode": null
734 | },
735 | {
736 | "id": "6-32-12",
737 | "type": 13,
738 | "rolNum": 32,
739 | "rowNum": 12,
740 | "layerNum": 6,
741 | "moldType": 1,
742 | "blockNode": null
743 | },
744 | {
745 | "id": "6-12-28",
746 | "type": 7,
747 | "rolNum": 12,
748 | "rowNum": 28,
749 | "layerNum": 6,
750 | "moldType": 1,
751 | "blockNode": null
752 | },
753 | {
754 | "id": "6-12-36",
755 | "type": 14,
756 | "rolNum": 12,
757 | "rowNum": 36,
758 | "layerNum": 6,
759 | "moldType": 1,
760 | "blockNode": null
761 | },
762 | {
763 | "id": "6-44-28",
764 | "type": 2,
765 | "rolNum": 44,
766 | "rowNum": 28,
767 | "layerNum": 6,
768 | "moldType": 1,
769 | "blockNode": null
770 | },
771 | {
772 | "id": "6-44-36",
773 | "type": 11,
774 | "rolNum": 44,
775 | "rowNum": 36,
776 | "layerNum": 6,
777 | "moldType": 1,
778 | "blockNode": null
779 | },
780 | {
781 | "id": "6-9-52",
782 | "type": 5,
783 | "rolNum": 9,
784 | "rowNum": 52,
785 | "layerNum": 6,
786 | "moldType": 2,
787 | "blockNode": null
788 | },
789 | {
790 | "id": "6-47-52",
791 | "type": 3,
792 | "rolNum": 47,
793 | "rowNum": 52,
794 | "layerNum": 6,
795 | "moldType": 2,
796 | "blockNode": null
797 | }
798 | ],
799 | "7": [
800 | {
801 | "id": "7-28-8",
802 | "type": 9,
803 | "rolNum": 28,
804 | "rowNum": 8,
805 | "layerNum": 7,
806 | "moldType": 1,
807 | "blockNode": null
808 | },
809 | {
810 | "id": "7-24-16",
811 | "type": 9,
812 | "rolNum": 24,
813 | "rowNum": 16,
814 | "layerNum": 7,
815 | "moldType": 1,
816 | "blockNode": null
817 | },
818 | {
819 | "id": "7-32-16",
820 | "type": 9,
821 | "rolNum": 32,
822 | "rowNum": 16,
823 | "layerNum": 7,
824 | "moldType": 1,
825 | "blockNode": null
826 | },
827 | {
828 | "id": "7-16-28",
829 | "type": 12,
830 | "rolNum": 16,
831 | "rowNum": 28,
832 | "layerNum": 7,
833 | "moldType": 1,
834 | "blockNode": null
835 | },
836 | {
837 | "id": "7-16-36",
838 | "type": 13,
839 | "rolNum": 16,
840 | "rowNum": 36,
841 | "layerNum": 7,
842 | "moldType": 1,
843 | "blockNode": null
844 | },
845 | {
846 | "id": "7-8-32",
847 | "type": 14,
848 | "rolNum": 8,
849 | "rowNum": 32,
850 | "layerNum": 7,
851 | "moldType": 1,
852 | "blockNode": null
853 | },
854 | {
855 | "id": "7-48-28",
856 | "type": 11,
857 | "rolNum": 48,
858 | "rowNum": 28,
859 | "layerNum": 7,
860 | "moldType": 1,
861 | "blockNode": null
862 | },
863 | {
864 | "id": "7-48-36",
865 | "type": 7,
866 | "rolNum": 48,
867 | "rowNum": 36,
868 | "layerNum": 7,
869 | "moldType": 1,
870 | "blockNode": null
871 | },
872 | {
873 | "id": "7-40-32",
874 | "type": 2,
875 | "rolNum": 40,
876 | "rowNum": 32,
877 | "layerNum": 7,
878 | "moldType": 1,
879 | "blockNode": null
880 | },
881 | {
882 | "id": "7-10-52",
883 | "type": 13,
884 | "rolNum": 10,
885 | "rowNum": 52,
886 | "layerNum": 7,
887 | "moldType": 2,
888 | "blockNode": null
889 | },
890 | {
891 | "id": "7-46-52",
892 | "type": 9,
893 | "rolNum": 46,
894 | "rowNum": 52,
895 | "layerNum": 7,
896 | "moldType": 2,
897 | "blockNode": null
898 | }
899 | ],
900 | "8": [
901 | {
902 | "id": "8-24-8",
903 | "type": 8,
904 | "rolNum": 24,
905 | "rowNum": 8,
906 | "layerNum": 8,
907 | "moldType": 1,
908 | "blockNode": null
909 | },
910 | {
911 | "id": "8-32-8",
912 | "type": 10,
913 | "rolNum": 32,
914 | "rowNum": 8,
915 | "layerNum": 8,
916 | "moldType": 1,
917 | "blockNode": null
918 | },
919 | {
920 | "id": "8-28-16",
921 | "type": 7,
922 | "rolNum": 28,
923 | "rowNum": 16,
924 | "layerNum": 8,
925 | "moldType": 1,
926 | "blockNode": null
927 | },
928 | {
929 | "id": "8-8-28",
930 | "type": 6,
931 | "rolNum": 8,
932 | "rowNum": 28,
933 | "layerNum": 8,
934 | "moldType": 1,
935 | "blockNode": null
936 | },
937 | {
938 | "id": "8-8-36",
939 | "type": 13,
940 | "rolNum": 8,
941 | "rowNum": 36,
942 | "layerNum": 8,
943 | "moldType": 1,
944 | "blockNode": null
945 | },
946 | {
947 | "id": "8-16-32",
948 | "type": 5,
949 | "rolNum": 16,
950 | "rowNum": 32,
951 | "layerNum": 8,
952 | "moldType": 1,
953 | "blockNode": null
954 | },
955 | {
956 | "id": "8-40-28",
957 | "type": 3,
958 | "rolNum": 40,
959 | "rowNum": 28,
960 | "layerNum": 8,
961 | "moldType": 1,
962 | "blockNode": null
963 | },
964 | {
965 | "id": "8-40-36",
966 | "type": 10,
967 | "rolNum": 40,
968 | "rowNum": 36,
969 | "layerNum": 8,
970 | "moldType": 1,
971 | "blockNode": null
972 | },
973 | {
974 | "id": "8-48-32",
975 | "type": 3,
976 | "rolNum": 48,
977 | "rowNum": 32,
978 | "layerNum": 8,
979 | "moldType": 1,
980 | "blockNode": null
981 | },
982 | {
983 | "id": "8-11-52",
984 | "type": 10,
985 | "rolNum": 11,
986 | "rowNum": 52,
987 | "layerNum": 8,
988 | "moldType": 2,
989 | "blockNode": null
990 | },
991 | {
992 | "id": "8-45-52",
993 | "type": 11,
994 | "rolNum": 45,
995 | "rowNum": 52,
996 | "layerNum": 8,
997 | "moldType": 2,
998 | "blockNode": null
999 | }
1000 | ],
1001 | "9": [
1002 | {
1003 | "id": "9-24-16",
1004 | "type": 12,
1005 | "rolNum": 24,
1006 | "rowNum": 16,
1007 | "layerNum": 9,
1008 | "moldType": 1,
1009 | "blockNode": null
1010 | },
1011 | {
1012 | "id": "9-32-16",
1013 | "type": 11,
1014 | "rolNum": 32,
1015 | "rowNum": 16,
1016 | "layerNum": 9,
1017 | "moldType": 1,
1018 | "blockNode": null
1019 | },
1020 | {
1021 | "id": "9-28-8",
1022 | "type": 11,
1023 | "rolNum": 28,
1024 | "rowNum": 8,
1025 | "layerNum": 9,
1026 | "moldType": 1,
1027 | "blockNode": null
1028 | },
1029 | {
1030 | "id": "9-12-28",
1031 | "type": 14,
1032 | "rolNum": 12,
1033 | "rowNum": 28,
1034 | "layerNum": 9,
1035 | "moldType": 1,
1036 | "blockNode": null
1037 | },
1038 | {
1039 | "id": "9-12-36",
1040 | "type": 12,
1041 | "rolNum": 12,
1042 | "rowNum": 36,
1043 | "layerNum": 9,
1044 | "moldType": 1,
1045 | "blockNode": null
1046 | },
1047 | {
1048 | "id": "9-44-28",
1049 | "type": 7,
1050 | "rolNum": 44,
1051 | "rowNum": 28,
1052 | "layerNum": 9,
1053 | "moldType": 1,
1054 | "blockNode": null
1055 | },
1056 | {
1057 | "id": "9-44-36",
1058 | "type": 11,
1059 | "rolNum": 44,
1060 | "rowNum": 36,
1061 | "layerNum": 9,
1062 | "moldType": 1,
1063 | "blockNode": null
1064 | },
1065 | {
1066 | "id": "9-20-4",
1067 | "type": 10,
1068 | "rolNum": 20,
1069 | "rowNum": 4,
1070 | "layerNum": 9,
1071 | "moldType": 1,
1072 | "blockNode": null
1073 | },
1074 | {
1075 | "id": "9-36-4",
1076 | "type": 8,
1077 | "rolNum": 36,
1078 | "rowNum": 4,
1079 | "layerNum": 9,
1080 | "moldType": 1,
1081 | "blockNode": null
1082 | },
1083 | {
1084 | "id": "9-12-52",
1085 | "type": 2,
1086 | "rolNum": 12,
1087 | "rowNum": 52,
1088 | "layerNum": 9,
1089 | "moldType": 2,
1090 | "blockNode": null
1091 | },
1092 | {
1093 | "id": "9-44-52",
1094 | "type": 13,
1095 | "rolNum": 44,
1096 | "rowNum": 52,
1097 | "layerNum": 9,
1098 | "moldType": 2,
1099 | "blockNode": null
1100 | }
1101 | ],
1102 | "10": [
1103 | {
1104 | "id": "10-24-12",
1105 | "type": 1,
1106 | "rolNum": 24,
1107 | "rowNum": 12,
1108 | "layerNum": 10,
1109 | "moldType": 1,
1110 | "blockNode": null
1111 | },
1112 | {
1113 | "id": "10-32-12",
1114 | "type": 6,
1115 | "rolNum": 32,
1116 | "rowNum": 12,
1117 | "layerNum": 10,
1118 | "moldType": 1,
1119 | "blockNode": null
1120 | },
1121 | {
1122 | "id": "10-8-32",
1123 | "type": 12,
1124 | "rolNum": 8,
1125 | "rowNum": 32,
1126 | "layerNum": 10,
1127 | "moldType": 1,
1128 | "blockNode": null
1129 | },
1130 | {
1131 | "id": "10-16-32",
1132 | "type": 12,
1133 | "rolNum": 16,
1134 | "rowNum": 32,
1135 | "layerNum": 10,
1136 | "moldType": 1,
1137 | "blockNode": null
1138 | },
1139 | {
1140 | "id": "10-40-32",
1141 | "type": 1,
1142 | "rolNum": 40,
1143 | "rowNum": 32,
1144 | "layerNum": 10,
1145 | "moldType": 1,
1146 | "blockNode": null
1147 | },
1148 | {
1149 | "id": "10-48-32",
1150 | "type": 11,
1151 | "rolNum": 48,
1152 | "rowNum": 32,
1153 | "layerNum": 10,
1154 | "moldType": 1,
1155 | "blockNode": null
1156 | },
1157 | {
1158 | "id": "10-8-40",
1159 | "type": 12,
1160 | "rolNum": 8,
1161 | "rowNum": 40,
1162 | "layerNum": 10,
1163 | "moldType": 1,
1164 | "blockNode": null
1165 | },
1166 | {
1167 | "id": "10-48-40",
1168 | "type": 11,
1169 | "rolNum": 48,
1170 | "rowNum": 40,
1171 | "layerNum": 10,
1172 | "moldType": 1,
1173 | "blockNode": null
1174 | },
1175 | {
1176 | "id": "10-16-40",
1177 | "type": 9,
1178 | "rolNum": 16,
1179 | "rowNum": 40,
1180 | "layerNum": 10,
1181 | "moldType": 1,
1182 | "blockNode": null
1183 | },
1184 | {
1185 | "id": "10-40-40",
1186 | "type": 4,
1187 | "rolNum": 40,
1188 | "rowNum": 40,
1189 | "layerNum": 10,
1190 | "moldType": 1,
1191 | "blockNode": null
1192 | },
1193 | {
1194 | "id": "10-20-20",
1195 | "type": 7,
1196 | "rolNum": 20,
1197 | "rowNum": 20,
1198 | "layerNum": 10,
1199 | "moldType": 1,
1200 | "blockNode": null
1201 | },
1202 | {
1203 | "id": "10-36-20",
1204 | "type": 1,
1205 | "rolNum": 36,
1206 | "rowNum": 20,
1207 | "layerNum": 10,
1208 | "moldType": 1,
1209 | "blockNode": null
1210 | },
1211 | {
1212 | "id": "10-13-52",
1213 | "type": 3,
1214 | "rolNum": 13,
1215 | "rowNum": 52,
1216 | "layerNum": 10,
1217 | "moldType": 2,
1218 | "blockNode": null
1219 | },
1220 | {
1221 | "id": "10-43-52",
1222 | "type": 7,
1223 | "rolNum": 43,
1224 | "rowNum": 52,
1225 | "layerNum": 10,
1226 | "moldType": 2,
1227 | "blockNode": null
1228 | }
1229 | ],
1230 | "11": [
1231 | {
1232 | "id": "11-12-28",
1233 | "type": 3,
1234 | "rolNum": 12,
1235 | "rowNum": 28,
1236 | "layerNum": 11,
1237 | "moldType": 1,
1238 | "blockNode": null
1239 | },
1240 | {
1241 | "id": "11-28-16",
1242 | "type": 8,
1243 | "rolNum": 28,
1244 | "rowNum": 16,
1245 | "layerNum": 11,
1246 | "moldType": 1,
1247 | "blockNode": null
1248 | },
1249 | {
1250 | "id": "11-44-28",
1251 | "type": 8,
1252 | "rolNum": 44,
1253 | "rowNum": 28,
1254 | "layerNum": 11,
1255 | "moldType": 1,
1256 | "blockNode": null
1257 | },
1258 | {
1259 | "id": "11-28-8",
1260 | "type": 5,
1261 | "rolNum": 28,
1262 | "rowNum": 8,
1263 | "layerNum": 11,
1264 | "moldType": 1,
1265 | "blockNode": null
1266 | },
1267 | {
1268 | "id": "11-12-36",
1269 | "type": 2,
1270 | "rolNum": 12,
1271 | "rowNum": 36,
1272 | "layerNum": 11,
1273 | "moldType": 1,
1274 | "blockNode": null
1275 | },
1276 | {
1277 | "id": "11-44-36",
1278 | "type": 14,
1279 | "rolNum": 44,
1280 | "rowNum": 36,
1281 | "layerNum": 11,
1282 | "moldType": 1,
1283 | "blockNode": null
1284 | },
1285 | {
1286 | "id": "11-20-12",
1287 | "type": 4,
1288 | "rolNum": 20,
1289 | "rowNum": 12,
1290 | "layerNum": 11,
1291 | "moldType": 1,
1292 | "blockNode": null
1293 | },
1294 | {
1295 | "id": "11-36-12",
1296 | "type": 2,
1297 | "rolNum": 36,
1298 | "rowNum": 12,
1299 | "layerNum": 11,
1300 | "moldType": 1,
1301 | "blockNode": null
1302 | },
1303 | {
1304 | "id": "11-14-52",
1305 | "type": 5,
1306 | "rolNum": 14,
1307 | "rowNum": 52,
1308 | "layerNum": 11,
1309 | "moldType": 2,
1310 | "blockNode": null
1311 | },
1312 | {
1313 | "id": "11-42-52",
1314 | "type": 10,
1315 | "rolNum": 42,
1316 | "rowNum": 52,
1317 | "layerNum": 11,
1318 | "moldType": 2,
1319 | "blockNode": null
1320 | }
1321 | ],
1322 | "12": [
1323 | {
1324 | "id": "12-28-20",
1325 | "type": 7,
1326 | "rolNum": 28,
1327 | "rowNum": 20,
1328 | "layerNum": 12,
1329 | "moldType": 1,
1330 | "blockNode": null
1331 | },
1332 | {
1333 | "id": "12-8-32",
1334 | "type": 3,
1335 | "rolNum": 8,
1336 | "rowNum": 32,
1337 | "layerNum": 12,
1338 | "moldType": 1,
1339 | "blockNode": null
1340 | },
1341 | {
1342 | "id": "12-16-32",
1343 | "type": 4,
1344 | "rolNum": 16,
1345 | "rowNum": 32,
1346 | "layerNum": 12,
1347 | "moldType": 1,
1348 | "blockNode": null
1349 | },
1350 | {
1351 | "id": "12-8-40",
1352 | "type": 1,
1353 | "rolNum": 8,
1354 | "rowNum": 40,
1355 | "layerNum": 12,
1356 | "moldType": 1,
1357 | "blockNode": null
1358 | },
1359 | {
1360 | "id": "12-16-40",
1361 | "type": 8,
1362 | "rolNum": 16,
1363 | "rowNum": 40,
1364 | "layerNum": 12,
1365 | "moldType": 1,
1366 | "blockNode": null
1367 | },
1368 | {
1369 | "id": "12-40-32",
1370 | "type": 10,
1371 | "rolNum": 40,
1372 | "rowNum": 32,
1373 | "layerNum": 12,
1374 | "moldType": 1,
1375 | "blockNode": null
1376 | },
1377 | {
1378 | "id": "12-48-32",
1379 | "type": 8,
1380 | "rolNum": 48,
1381 | "rowNum": 32,
1382 | "layerNum": 12,
1383 | "moldType": 1,
1384 | "blockNode": null
1385 | },
1386 | {
1387 | "id": "12-40-40",
1388 | "type": 3,
1389 | "rolNum": 40,
1390 | "rowNum": 40,
1391 | "layerNum": 12,
1392 | "moldType": 1,
1393 | "blockNode": null
1394 | },
1395 | {
1396 | "id": "12-48-40",
1397 | "type": 1,
1398 | "rolNum": 48,
1399 | "rowNum": 40,
1400 | "layerNum": 12,
1401 | "moldType": 1,
1402 | "blockNode": null
1403 | },
1404 | {
1405 | "id": "12-16-8",
1406 | "type": 2,
1407 | "rolNum": 16,
1408 | "rowNum": 8,
1409 | "layerNum": 12,
1410 | "moldType": 1,
1411 | "blockNode": null
1412 | },
1413 | {
1414 | "id": "12-24-8",
1415 | "type": 4,
1416 | "rolNum": 24,
1417 | "rowNum": 8,
1418 | "layerNum": 12,
1419 | "moldType": 1,
1420 | "blockNode": null
1421 | },
1422 | {
1423 | "id": "12-32-8",
1424 | "type": 13,
1425 | "rolNum": 32,
1426 | "rowNum": 8,
1427 | "layerNum": 12,
1428 | "moldType": 1,
1429 | "blockNode": null
1430 | },
1431 | {
1432 | "id": "12-40-8",
1433 | "type": 6,
1434 | "rolNum": 40,
1435 | "rowNum": 8,
1436 | "layerNum": 12,
1437 | "moldType": 1,
1438 | "blockNode": null
1439 | },
1440 | {
1441 | "id": "12-15-52",
1442 | "type": 1,
1443 | "rolNum": 15,
1444 | "rowNum": 52,
1445 | "layerNum": 12,
1446 | "moldType": 2,
1447 | "blockNode": null
1448 | },
1449 | {
1450 | "id": "12-41-52",
1451 | "type": 8,
1452 | "rolNum": 41,
1453 | "rowNum": 52,
1454 | "layerNum": 12,
1455 | "moldType": 2,
1456 | "blockNode": null
1457 | }
1458 | ],
1459 | "13": [
1460 | {
1461 | "id": "13-28-16",
1462 | "type": 8,
1463 | "rolNum": 28,
1464 | "rowNum": 16,
1465 | "layerNum": 13,
1466 | "moldType": 1,
1467 | "blockNode": null
1468 | },
1469 | {
1470 | "id": "13-12-28",
1471 | "type": 4,
1472 | "rolNum": 12,
1473 | "rowNum": 28,
1474 | "layerNum": 13,
1475 | "moldType": 1,
1476 | "blockNode": null
1477 | },
1478 | {
1479 | "id": "13-12-36",
1480 | "type": 2,
1481 | "rolNum": 12,
1482 | "rowNum": 36,
1483 | "layerNum": 13,
1484 | "moldType": 1,
1485 | "blockNode": null
1486 | },
1487 | {
1488 | "id": "13-44-28",
1489 | "type": 14,
1490 | "rolNum": 44,
1491 | "rowNum": 28,
1492 | "layerNum": 13,
1493 | "moldType": 1,
1494 | "blockNode": null
1495 | },
1496 | {
1497 | "id": "13-44-36",
1498 | "type": 10,
1499 | "rolNum": 44,
1500 | "rowNum": 36,
1501 | "layerNum": 13,
1502 | "moldType": 1,
1503 | "blockNode": null
1504 | },
1505 | {
1506 | "id": "13-4-40",
1507 | "type": 10,
1508 | "rolNum": 4,
1509 | "rowNum": 40,
1510 | "layerNum": 13,
1511 | "moldType": 1,
1512 | "blockNode": null
1513 | },
1514 | {
1515 | "id": "13-52-40",
1516 | "type": 1,
1517 | "rolNum": 52,
1518 | "rowNum": 40,
1519 | "layerNum": 13,
1520 | "moldType": 1,
1521 | "blockNode": null
1522 | },
1523 | {
1524 | "id": "13-20-40",
1525 | "type": 12,
1526 | "rolNum": 20,
1527 | "rowNum": 40,
1528 | "layerNum": 13,
1529 | "moldType": 1,
1530 | "blockNode": null
1531 | },
1532 | {
1533 | "id": "13-36-40",
1534 | "type": 6,
1535 | "rolNum": 36,
1536 | "rowNum": 40,
1537 | "layerNum": 13,
1538 | "moldType": 1,
1539 | "blockNode": null
1540 | },
1541 | {
1542 | "id": "13-16-52",
1543 | "type": 9,
1544 | "rolNum": 16,
1545 | "rowNum": 52,
1546 | "layerNum": 13,
1547 | "moldType": 2,
1548 | "blockNode": null
1549 | },
1550 | {
1551 | "id": "13-40-52",
1552 | "type": 12,
1553 | "rolNum": 40,
1554 | "rowNum": 52,
1555 | "layerNum": 13,
1556 | "moldType": 2,
1557 | "blockNode": null
1558 | },
1559 | {
1560 | "id": "13-12-12",
1561 | "type": 2,
1562 | "rolNum": 12,
1563 | "rowNum": 12,
1564 | "layerNum": 13,
1565 | "moldType": 1,
1566 | "blockNode": null
1567 | },
1568 | {
1569 | "id": "13-20-12",
1570 | "type": 9,
1571 | "rolNum": 20,
1572 | "rowNum": 12,
1573 | "layerNum": 13,
1574 | "moldType": 1,
1575 | "blockNode": null
1576 | },
1577 | {
1578 | "id": "13-36-12",
1579 | "type": 10,
1580 | "rolNum": 36,
1581 | "rowNum": 12,
1582 | "layerNum": 13,
1583 | "moldType": 1,
1584 | "blockNode": null
1585 | },
1586 | {
1587 | "id": "13-44-12",
1588 | "type": 7,
1589 | "rolNum": 44,
1590 | "rowNum": 12,
1591 | "layerNum": 13,
1592 | "moldType": 1,
1593 | "blockNode": null
1594 | }
1595 | ],
1596 | "14": [
1597 | {
1598 | "id": "14-8-32",
1599 | "type": 8,
1600 | "rolNum": 8,
1601 | "rowNum": 32,
1602 | "layerNum": 14,
1603 | "moldType": 1,
1604 | "blockNode": null
1605 | },
1606 | {
1607 | "id": "14-16-32",
1608 | "type": 5,
1609 | "rolNum": 16,
1610 | "rowNum": 32,
1611 | "layerNum": 14,
1612 | "moldType": 1,
1613 | "blockNode": null
1614 | },
1615 | {
1616 | "id": "14-12-40",
1617 | "type": 4,
1618 | "rolNum": 12,
1619 | "rowNum": 40,
1620 | "layerNum": 14,
1621 | "moldType": 1,
1622 | "blockNode": null
1623 | },
1624 | {
1625 | "id": "14-40-32",
1626 | "type": 4,
1627 | "rolNum": 40,
1628 | "rowNum": 32,
1629 | "layerNum": 14,
1630 | "moldType": 1,
1631 | "blockNode": null
1632 | },
1633 | {
1634 | "id": "14-48-32",
1635 | "type": 4,
1636 | "rolNum": 48,
1637 | "rowNum": 32,
1638 | "layerNum": 14,
1639 | "moldType": 1,
1640 | "blockNode": null
1641 | },
1642 | {
1643 | "id": "14-44-40",
1644 | "type": 10,
1645 | "rolNum": 44,
1646 | "rowNum": 40,
1647 | "layerNum": 14,
1648 | "moldType": 1,
1649 | "blockNode": null
1650 | },
1651 | {
1652 | "id": "14-28-20",
1653 | "type": 5,
1654 | "rolNum": 28,
1655 | "rowNum": 20,
1656 | "layerNum": 14,
1657 | "moldType": 1,
1658 | "blockNode": null
1659 | },
1660 | {
1661 | "id": "14-24-40",
1662 | "type": 10,
1663 | "rolNum": 24,
1664 | "rowNum": 40,
1665 | "layerNum": 14,
1666 | "moldType": 1,
1667 | "blockNode": null
1668 | },
1669 | {
1670 | "id": "14-32-40",
1671 | "type": 3,
1672 | "rolNum": 32,
1673 | "rowNum": 40,
1674 | "layerNum": 14,
1675 | "moldType": 1,
1676 | "blockNode": null
1677 | }
1678 | ],
1679 | "15": [
1680 | {
1681 | "id": "15-8-28",
1682 | "type": 4,
1683 | "rolNum": 8,
1684 | "rowNum": 28,
1685 | "layerNum": 15,
1686 | "moldType": 1,
1687 | "blockNode": null
1688 | },
1689 | {
1690 | "id": "15-16-28",
1691 | "type": 2,
1692 | "rolNum": 16,
1693 | "rowNum": 28,
1694 | "layerNum": 15,
1695 | "moldType": 1,
1696 | "blockNode": null
1697 | },
1698 | {
1699 | "id": "15-12-36",
1700 | "type": 5,
1701 | "rolNum": 12,
1702 | "rowNum": 36,
1703 | "layerNum": 15,
1704 | "moldType": 1,
1705 | "blockNode": null
1706 | },
1707 | {
1708 | "id": "15-40-28",
1709 | "type": 3,
1710 | "rolNum": 40,
1711 | "rowNum": 28,
1712 | "layerNum": 15,
1713 | "moldType": 1,
1714 | "blockNode": null
1715 | },
1716 | {
1717 | "id": "15-48-28",
1718 | "type": 12,
1719 | "rolNum": 48,
1720 | "rowNum": 28,
1721 | "layerNum": 15,
1722 | "moldType": 1,
1723 | "blockNode": null
1724 | },
1725 | {
1726 | "id": "15-44-36",
1727 | "type": 7,
1728 | "rolNum": 44,
1729 | "rowNum": 36,
1730 | "layerNum": 15,
1731 | "moldType": 1,
1732 | "blockNode": null
1733 | },
1734 | {
1735 | "id": "15-28-24",
1736 | "type": 1,
1737 | "rolNum": 28,
1738 | "rowNum": 24,
1739 | "layerNum": 15,
1740 | "moldType": 1,
1741 | "blockNode": null
1742 | },
1743 | {
1744 | "id": "15-28-16",
1745 | "type": 14,
1746 | "rolNum": 28,
1747 | "rowNum": 16,
1748 | "layerNum": 15,
1749 | "moldType": 1,
1750 | "blockNode": null
1751 | }
1752 | ],
1753 | "16": [
1754 | {
1755 | "id": "16-12-32",
1756 | "type": 7,
1757 | "rolNum": 12,
1758 | "rowNum": 32,
1759 | "layerNum": 16,
1760 | "moldType": 1,
1761 | "blockNode": null
1762 | },
1763 | {
1764 | "id": "16-44-32",
1765 | "type": 8,
1766 | "rolNum": 44,
1767 | "rowNum": 32,
1768 | "layerNum": 16,
1769 | "moldType": 1,
1770 | "blockNode": null
1771 | },
1772 | {
1773 | "id": "16-28-28",
1774 | "type": 1,
1775 | "rolNum": 28,
1776 | "rowNum": 28,
1777 | "layerNum": 16,
1778 | "moldType": 1,
1779 | "blockNode": null
1780 | },
1781 | {
1782 | "id": "16-4-24",
1783 | "type": 3,
1784 | "rolNum": 4,
1785 | "rowNum": 24,
1786 | "layerNum": 16,
1787 | "moldType": 1,
1788 | "blockNode": null
1789 | },
1790 | {
1791 | "id": "16-4-32",
1792 | "type": 1,
1793 | "rolNum": 4,
1794 | "rowNum": 32,
1795 | "layerNum": 16,
1796 | "moldType": 1,
1797 | "blockNode": null
1798 | },
1799 | {
1800 | "id": "16-52-24",
1801 | "type": 10,
1802 | "rolNum": 52,
1803 | "rowNum": 24,
1804 | "layerNum": 16,
1805 | "moldType": 1,
1806 | "blockNode": null
1807 | },
1808 | {
1809 | "id": "16-52-32",
1810 | "type": 5,
1811 | "rolNum": 52,
1812 | "rowNum": 32,
1813 | "layerNum": 16,
1814 | "moldType": 1,
1815 | "blockNode": null
1816 | },
1817 | {
1818 | "id": "16-12-40",
1819 | "type": 14,
1820 | "rolNum": 12,
1821 | "rowNum": 40,
1822 | "layerNum": 16,
1823 | "moldType": 1,
1824 | "blockNode": null
1825 | },
1826 | {
1827 | "id": "16-44-40",
1828 | "type": 9,
1829 | "rolNum": 44,
1830 | "rowNum": 40,
1831 | "layerNum": 16,
1832 | "moldType": 1,
1833 | "blockNode": null
1834 | }
1835 | ],
1836 | "17": [
1837 | {
1838 | "id": "17-16-32",
1839 | "type": 13,
1840 | "rolNum": 16,
1841 | "rowNum": 32,
1842 | "layerNum": 17,
1843 | "moldType": 1,
1844 | "blockNode": null
1845 | },
1846 | {
1847 | "id": "17-40-32",
1848 | "type": 14,
1849 | "rolNum": 40,
1850 | "rowNum": 32,
1851 | "layerNum": 17,
1852 | "moldType": 1,
1853 | "blockNode": null
1854 | },
1855 | {
1856 | "id": "17-28-32",
1857 | "type": 4,
1858 | "rolNum": 28,
1859 | "rowNum": 32,
1860 | "layerNum": 17,
1861 | "moldType": 1,
1862 | "blockNode": null
1863 | },
1864 | {
1865 | "id": "17-28-24",
1866 | "type": 10,
1867 | "rolNum": 28,
1868 | "rowNum": 24,
1869 | "layerNum": 17,
1870 | "moldType": 1,
1871 | "blockNode": null
1872 | }
1873 | ],
1874 | "18": [
1875 | {
1876 | "id": "18-20-32",
1877 | "type": 9,
1878 | "rolNum": 20,
1879 | "rowNum": 32,
1880 | "layerNum": 18,
1881 | "moldType": 1,
1882 | "blockNode": null
1883 | },
1884 | {
1885 | "id": "18-36-32",
1886 | "type": 2,
1887 | "rolNum": 36,
1888 | "rowNum": 32,
1889 | "layerNum": 18,
1890 | "moldType": 1,
1891 | "blockNode": null
1892 | },
1893 | {
1894 | "id": "18-12-28",
1895 | "type": 6,
1896 | "rolNum": 12,
1897 | "rowNum": 28,
1898 | "layerNum": 18,
1899 | "moldType": 1,
1900 | "blockNode": null
1901 | },
1902 | {
1903 | "id": "18-44-28",
1904 | "type": 2,
1905 | "rolNum": 44,
1906 | "rowNum": 28,
1907 | "layerNum": 18,
1908 | "moldType": 1,
1909 | "blockNode": null
1910 | }
1911 | ],
1912 | "19": [
1913 | {
1914 | "id": "19-20-28",
1915 | "type": 5,
1916 | "rolNum": 20,
1917 | "rowNum": 28,
1918 | "layerNum": 19,
1919 | "moldType": 1,
1920 | "blockNode": null
1921 | },
1922 | {
1923 | "id": "19-36-28",
1924 | "type": 3,
1925 | "rolNum": 36,
1926 | "rowNum": 28,
1927 | "layerNum": 19,
1928 | "moldType": 1,
1929 | "blockNode": null
1930 | },
1931 | {
1932 | "id": "19-8-24",
1933 | "type": 4,
1934 | "rolNum": 8,
1935 | "rowNum": 24,
1936 | "layerNum": 19,
1937 | "moldType": 1,
1938 | "blockNode": null
1939 | },
1940 | {
1941 | "id": "19-8-32",
1942 | "type": 13,
1943 | "rolNum": 8,
1944 | "rowNum": 32,
1945 | "layerNum": 19,
1946 | "moldType": 1,
1947 | "blockNode": null
1948 | },
1949 | {
1950 | "id": "19-48-24",
1951 | "type": 8,
1952 | "rolNum": 48,
1953 | "rowNum": 24,
1954 | "layerNum": 19,
1955 | "moldType": 1,
1956 | "blockNode": null
1957 | },
1958 | {
1959 | "id": "19-48-32",
1960 | "type": 8,
1961 | "rolNum": 48,
1962 | "rowNum": 32,
1963 | "layerNum": 19,
1964 | "moldType": 1,
1965 | "blockNode": null
1966 | }
1967 | ],
1968 | "20": [
1969 | {
1970 | "id": "20-16-32",
1971 | "type": 14,
1972 | "rolNum": 16,
1973 | "rowNum": 32,
1974 | "layerNum": 20,
1975 | "moldType": 1,
1976 | "blockNode": null
1977 | },
1978 | {
1979 | "id": "20-24-32",
1980 | "type": 14,
1981 | "rolNum": 24,
1982 | "rowNum": 32,
1983 | "layerNum": 20,
1984 | "moldType": 1,
1985 | "blockNode": null
1986 | },
1987 | {
1988 | "id": "20-32-32",
1989 | "type": 5,
1990 | "rolNum": 32,
1991 | "rowNum": 32,
1992 | "layerNum": 20,
1993 | "moldType": 1,
1994 | "blockNode": null
1995 | },
1996 | {
1997 | "id": "20-40-32",
1998 | "type": 11,
1999 | "rolNum": 40,
2000 | "rowNum": 32,
2001 | "layerNum": 20,
2002 | "moldType": 1,
2003 | "blockNode": null
2004 | },
2005 | {
2006 | "id": "20-12-20",
2007 | "type": 14,
2008 | "rolNum": 12,
2009 | "rowNum": 20,
2010 | "layerNum": 20,
2011 | "moldType": 1,
2012 | "blockNode": null
2013 | },
2014 | {
2015 | "id": "20-44-20",
2016 | "type": 7,
2017 | "rolNum": 44,
2018 | "rowNum": 20,
2019 | "layerNum": 20,
2020 | "moldType": 1,
2021 | "blockNode": null
2022 | }
2023 | ],
2024 | "21": [
2025 | {
2026 | "id": "21-12-28",
2027 | "type": 7,
2028 | "rolNum": 12,
2029 | "rowNum": 28,
2030 | "layerNum": 21,
2031 | "moldType": 1,
2032 | "blockNode": null
2033 | },
2034 | {
2035 | "id": "21-20-28",
2036 | "type": 6,
2037 | "rolNum": 20,
2038 | "rowNum": 28,
2039 | "layerNum": 21,
2040 | "moldType": 1,
2041 | "blockNode": null
2042 | },
2043 | {
2044 | "id": "21-36-28",
2045 | "type": 2,
2046 | "rolNum": 36,
2047 | "rowNum": 28,
2048 | "layerNum": 21,
2049 | "moldType": 1,
2050 | "blockNode": null
2051 | },
2052 | {
2053 | "id": "21-44-28",
2054 | "type": 9,
2055 | "rolNum": 44,
2056 | "rowNum": 28,
2057 | "layerNum": 21,
2058 | "moldType": 1,
2059 | "blockNode": null
2060 | }
2061 | ]
2062 | },
2063 | "layers": [
2064 | "1",
2065 | "2",
2066 | "3",
2067 | "4",
2068 | "5",
2069 | "6",
2070 | "7",
2071 | "8",
2072 | "9",
2073 | "10",
2074 | "11",
2075 | "12",
2076 | "13",
2077 | "14",
2078 | "15",
2079 | "16",
2080 | "17",
2081 | "18",
2082 | "19",
2083 | "20",
2084 | "21"
2085 | ],
2086 | "operations": [
2087 | "21-12-28",
2088 | "20-44-20",
2089 | "13-44-12",
2090 | "21-44-28",
2091 | "16-44-40",
2092 | "13-20-12",
2093 | "17-28-24",
2094 | "14-24-40",
2095 | "13-36-12",
2096 | "21-20-28",
2097 | "12-40-8",
2098 | "5-48-16",
2099 | "20-16-32",
2100 | "20-24-32",
2101 | "20-12-20",
2102 | "21-36-28",
2103 | "13-12-12",
2104 | "12-16-8",
2105 | "19-8-24",
2106 | "12-24-8",
2107 | "11-20-12",
2108 | "16-4-24",
2109 | "14-32-40",
2110 | "4-4-0",
2111 | "13-52-40",
2112 | "10-36-20",
2113 | "5-8-8",
2114 | "13-36-40",
2115 | "4-52-16",
2116 | "3-12-4",
2117 | "5-48-8",
2118 | "4-4-8",
2119 | "3-44-4",
2120 | "19-8-32",
2121 | "12-32-8",
2122 | "4-52-8",
2123 | "20-32-32",
2124 | "19-20-28",
2125 | "11-28-8",
2126 | "19-48-24",
2127 | "19-48-32",
2128 | "9-36-4",
2129 | "16-52-24",
2130 | "13-4-40",
2131 | "9-20-4",
2132 | "16-4-32",
2133 | "2-28-0",
2134 | "2-16-0",
2135 | "20-40-32",
2136 | "4-52-0",
2137 | "1-32-0",
2138 | "19-36-28",
2139 | "3-4-4",
2140 | "3-44-12",
2141 | "18-44-28",
2142 | "18-36-32",
2143 | "11-36-12",
2144 | "18-20-32",
2145 | "13-16-52",
2146 | "2-8-0",
2147 | "17-40-32",
2148 | "16-12-40",
2149 | "15-28-16",
2150 | "13-20-40",
2151 | "13-40-52",
2152 | "1-24-0",
2153 | "16-44-32",
2154 | "5-8-16",
2155 | "12-41-52",
2156 | "15-44-36",
2157 | "11-42-52",
2158 | "3-52-4",
2159 | "14-44-40",
2160 | "3-52-12",
2161 | "10-43-52",
2162 | "2-28-40",
2163 | "2-48-8",
2164 | "17-28-32",
2165 | "3-12-12",
2166 | "16-28-28",
2167 | "15-28-24",
2168 | "12-15-52",
2169 | "11-14-52",
2170 | "15-40-28",
2171 | "10-13-52",
2172 | "16-52-32",
2173 | "9-12-52",
2174 | "14-28-20",
2175 | "15-48-28",
2176 | "14-40-32",
2177 | "14-48-32",
2178 | "8-11-52",
2179 | "9-44-52",
2180 | "7-10-52",
2181 | "1-24-40",
2182 | "18-12-28",
2183 | "17-16-32",
2184 | "4-4-16",
2185 | "3-4-12",
2186 | "1-32-40",
2187 | "16-12-32",
2188 | "2-8-8",
2189 | "10-20-20",
2190 | "13-44-36",
2191 | "13-44-28",
2192 | "12-40-32",
2193 | "15-12-36",
2194 | "6-9-52",
2195 | "1-4-4",
2196 | "5-8-52",
2197 | "15-8-28",
2198 | "1-12-4",
2199 | "12-48-32",
2200 | "13-28-16",
2201 | "14-8-32",
2202 | "14-12-40",
2203 | "2-40-0",
2204 | "2-48-0",
2205 | "1-12-12",
2206 | "8-45-52",
2207 | "12-28-20",
2208 | "12-48-40",
2209 | "4-7-52",
2210 | "1-52-12",
2211 | "12-40-40",
2212 | "11-44-36",
2213 | "3-6-52",
2214 | "2-5-52",
2215 | "10-48-40",
2216 | "7-46-52",
2217 | "1-4-52",
2218 | "1-52-4",
2219 | "15-16-28",
2220 | "14-16-32",
2221 | "13-12-36",
2222 | "1-44-20",
2223 | "13-12-28",
2224 | "12-8-32",
2225 | "6-47-52",
2226 | "11-44-28",
2227 | "11-28-16",
2228 | "12-16-40",
2229 | "10-32-12",
2230 | "12-16-32",
2231 | "10-40-40",
2232 | "10-24-12",
2233 | "12-8-40",
2234 | "10-40-32",
2235 | "10-48-32",
2236 | "9-28-8",
2237 | "9-44-36",
2238 | "9-44-28",
2239 | "8-48-32",
2240 | "11-12-28",
2241 | "11-12-36",
2242 | "8-40-28",
2243 | "10-8-32",
2244 | "10-16-32",
2245 | "10-8-40",
2246 | "9-12-28",
2247 | "8-8-28",
2248 | "1-44-4",
2249 | "9-32-16",
2250 | "7-48-28",
2251 | "1-44-12",
2252 | "8-32-8",
2253 | "8-40-36",
2254 | "7-40-32",
2255 | "6-44-28",
2256 | "8-24-8",
2257 | "1-4-12",
2258 | "10-16-40",
2259 | "5-48-52",
2260 | "7-28-8",
2261 | "9-12-36",
2262 | "8-16-32",
2263 | "9-24-16",
2264 | "7-16-28",
2265 | "5-48-28",
2266 | "8-8-36",
2267 | "7-16-36",
2268 | "7-8-32",
2269 | "6-12-36",
2270 | "8-28-16",
2271 | "7-32-16",
2272 | "6-32-12",
2273 | "7-24-16",
2274 | "5-8-36",
2275 | "7-48-36",
2276 | "6-12-28",
2277 | "6-24-12",
2278 | "6-44-36",
2279 | "5-24-8",
2280 | "5-40-36",
2281 | "4-44-32",
2282 | "3-48-36",
2283 | "5-32-16",
2284 | "4-28-12",
2285 | "3-32-8",
2286 | "3-40-28",
2287 | "2-44-28",
2288 | "3-24-16",
2289 | "1-48-28",
2290 | "5-16-28",
2291 | "4-12-32",
2292 | "3-8-28",
2293 | "2-32-12",
2294 | "4-49-52",
2295 | "3-50-52",
2296 | "2-24-12",
2297 | "2-51-52",
2298 | "3-16-36",
2299 | "2-12-36",
2300 | "1-32-16",
2301 | "2-44-36",
2302 | "2-12-28",
2303 | "1-16-28",
2304 | "1-12-20",
2305 | "1-24-8",
2306 | "1-40-36",
2307 | "1-8-36",
2308 | "1-52-52"
2309 | ]
2310 | };
--------------------------------------------------------------------------------