gotchi-battler-game-logic 3.0.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.cursor/rules/cursor-rules.mdc +67 -0
  2. package/.cursor/rules/directory-structure.mdc +63 -0
  3. package/.cursor/rules/self-improvement.mdc +64 -0
  4. package/.cursor/rules/tech-stack.mdc +99 -0
  5. package/README.md +4 -0
  6. package/eslint.config.js +31 -0
  7. package/game-logic/index.js +2 -6
  8. package/game-logic/v1.4/constants.js +0 -23
  9. package/game-logic/v1.4/index.js +64 -56
  10. package/game-logic/v1.5/constants.js +0 -23
  11. package/game-logic/v1.5/index.js +27 -21
  12. package/game-logic/v1.6/constants.js +0 -23
  13. package/game-logic/v1.6/index.js +27 -21
  14. package/game-logic/v1.7/constants.js +0 -23
  15. package/game-logic/v1.7/helpers.js +2 -2
  16. package/game-logic/v1.7/index.js +24 -18
  17. package/game-logic/v1.8/constants.js +0 -23
  18. package/game-logic/v1.8/helpers.js +2 -2
  19. package/game-logic/v1.8/index.js +25 -19
  20. package/game-logic/v2.0/constants.js +112 -0
  21. package/game-logic/v2.0/helpers.js +713 -0
  22. package/game-logic/v2.0/index.js +782 -0
  23. package/game-logic/v2.0/statuses.json +439 -0
  24. package/package.json +11 -4
  25. package/schemas/crystal.js +14 -0
  26. package/schemas/effect.js +25 -0
  27. package/schemas/gotchi.js +53 -0
  28. package/schemas/ingameteam.js +14 -0
  29. package/schemas/item.js +13 -0
  30. package/schemas/leaderskill.js +15 -0
  31. package/schemas/leaderskillstatus.js +12 -0
  32. package/schemas/special.js +22 -0
  33. package/schemas/team.js +24 -0
  34. package/schemas/team.json +252 -114
  35. package/scripts/balancing/createTrainingGotchis.js +44 -44
  36. package/scripts/balancing/extractOnchainTraits.js +3 -3
  37. package/scripts/balancing/fixTrainingGotchis.js +41 -41
  38. package/scripts/balancing/processSims.js +5 -5
  39. package/scripts/balancing/sims.js +8 -15
  40. package/scripts/balancing/v1.7/setTeamPositions.js +2 -2
  41. package/scripts/balancing/v1.7.1/setTeamPositions.js +2 -2
  42. package/scripts/balancing/v1.7.2/setTeamPositions.js +2 -2
  43. package/scripts/balancing/v1.7.3/setTeamPositions.js +2 -2
  44. package/scripts/data/dungeon_mob_1.json +87 -0
  45. package/scripts/data/dungeon_mob_2.json +87 -0
  46. package/scripts/data/immaterialTeam1.json +374 -0
  47. package/scripts/data/immaterialTeam2.json +365 -0
  48. package/scripts/generateAllSpecialsLogs.js +93 -0
  49. package/scripts/generateSpecialLogs.js +94 -0
  50. package/scripts/runCampaignBattles.js +41 -0
  51. package/scripts/runLocalBattle.js +6 -3
  52. package/scripts/runLocalDungeon.js +52 -0
  53. package/scripts/runPvPBattle.js +15 -0
  54. package/scripts/runRealBattle.js +8 -8
  55. package/scripts/simRealBattle.js +8 -8
  56. package/scripts/validateBattle.js +12 -14
  57. package/scripts/validateTournament.js +9 -9
  58. package/tests/getModifiedStats.test.js +78 -0
  59. package/utils/errors.js +13 -13
  60. package/utils/transforms.js +2 -8
  61. package/scripts/output/.gitkeep +0 -0
@@ -4,60 +4,60 @@ const { mapGotchi } = require('../../utils/mapGotchi')
4
4
 
5
5
  const specials = [
6
6
  {
7
- "id": 1,
8
- "class": "Ninja",
9
- "name": "Spectral strike",
10
- "cooldown": 0,
11
- "leaderPassive": "Sharpen blades"
7
+ 'id': 1,
8
+ 'class': 'Ninja',
9
+ 'name': 'Spectral strike',
10
+ 'cooldown': 0,
11
+ 'leaderPassive': 'Sharpen blades'
12
12
  },
13
13
  {
14
- "id": 2,
15
- "class": "Enlightened",
16
- "name": "Meditate",
17
- "cooldown": 0,
18
- "leaderPassive": "Cloud of Zen"
14
+ 'id': 2,
15
+ 'class': 'Enlightened',
16
+ 'name': 'Meditate',
17
+ 'cooldown': 0,
18
+ 'leaderPassive': 'Cloud of Zen'
19
19
  },
20
20
  {
21
- "id": 3,
22
- "class": "Cleaver",
23
- "name": "Cleave",
24
- "cooldown": 2,
25
- "leaderPassive": "Frenzy"
21
+ 'id': 3,
22
+ 'class': 'Cleaver',
23
+ 'name': 'Cleave',
24
+ 'cooldown': 2,
25
+ 'leaderPassive': 'Frenzy'
26
26
  },
27
27
  {
28
- "id": 4,
29
- "class": "Tank",
30
- "name": "Taunt",
31
- "cooldown": 0,
32
- "leaderPassive": "Fortify"
28
+ 'id': 4,
29
+ 'class': 'Tank',
30
+ 'name': 'Taunt',
31
+ 'cooldown': 0,
32
+ 'leaderPassive': 'Fortify'
33
33
  },
34
34
  {
35
- "id": 5,
36
- "class": "Cursed",
37
- "name": "Curse",
38
- "cooldown": 0,
39
- "leaderPassive": "Spread the fear"
35
+ 'id': 5,
36
+ 'class': 'Cursed',
37
+ 'name': 'Curse',
38
+ 'cooldown': 0,
39
+ 'leaderPassive': 'Spread the fear'
40
40
  },
41
41
  {
42
- "id": 6,
43
- "class": "Healer",
44
- "name": "Blessing",
45
- "cooldown": 0,
46
- "leaderPassive": "Cleansing Aura"
42
+ 'id': 6,
43
+ 'class': 'Healer',
44
+ 'name': 'Blessing',
45
+ 'cooldown': 0,
46
+ 'leaderPassive': 'Cleansing Aura'
47
47
  },
48
48
  {
49
- "id": 7,
50
- "class": "Mage",
51
- "name": "Thunder",
52
- "cooldown": 2,
53
- "leaderPassive": "Channel the coven"
49
+ 'id': 7,
50
+ 'class': 'Mage',
51
+ 'name': 'Thunder',
52
+ 'cooldown': 2,
53
+ 'leaderPassive': 'Channel the coven'
54
54
  },
55
55
  {
56
- "id": 8,
57
- "class": "Troll",
58
- "name": "Devestating Smash",
59
- "cooldown": 2,
60
- "leaderPassive": "Clan momentum"
56
+ 'id': 8,
57
+ 'class': 'Troll',
58
+ 'name': 'Devestating Smash',
59
+ 'cooldown': 2,
60
+ 'leaderPassive': 'Clan momentum'
61
61
  }
62
62
  ]
63
63
 
@@ -65,7 +65,7 @@ const classes = ['Ninja','Enlightened','Cleaver','Tank','Cursed','Healer', 'Mage
65
65
  const powerLevels = ['Godlike', 'Mythical', 'Legendary', 'Rare', 'Uncommon', 'Common', 'Garbage']
66
66
 
67
67
  const addAvgGotchs = () => {
68
- const statsToOverwrite = ["speed", "health", "crit", "armor", "evade", "resist", "accuracy"]
68
+ const statsToOverwrite = ['speed', 'health', 'crit', 'armor', 'evade', 'resist', 'accuracy']
69
69
 
70
70
  const avgGotchis = [];
71
71
 
@@ -41,16 +41,16 @@ const classes = ['Ninja','Enlightened','Cleaver','Tank','Cursed','Healer', 'Mage
41
41
 
42
42
  const calculateKpis = (data) => {
43
43
  // Extract wins values
44
- const wins = data.map(item => item.wins);
44
+ const wins = data.map(item => item.wins)
45
45
 
46
46
  // Calculate the mean of wins
47
- const winsMean = wins.reduce((sum, value) => sum + value, 0) / wins.length;
47
+ const winsMean = wins.reduce((sum, value) => sum + value, 0) / wins.length
48
48
 
49
49
  // Calculate the wins per slot
50
50
  const winsPerSlot = winsMean / 5
51
51
 
52
52
  // Calculate the standard deviation of wins
53
- const winsVariance = wins.reduce((sum, value) => sum + Math.pow(value - winsMean, 2), 0) / (wins.length - 1);
53
+ const winsVariance = wins.reduce((sum, value) => sum + Math.pow(value - winsMean, 2), 0) / (wins.length - 1)
54
54
  const winsStdev = Math.sqrt(winsVariance)
55
55
 
56
56
  // Calculate Interquartile Range (IQR)
@@ -91,8 +91,8 @@ const calculateKpis = (data) => {
91
91
  // G is power level, avg is trait combo, 1 is class number, B is formation position
92
92
  const leaderWins = data.filter(item => item.slot1.includes(`${i + 1}`)).map(item => item.wins)
93
93
 
94
- const leaderWinsMean = leaderWins.reduce((sum, value) => sum + value, 0) / leaderWins.length;
95
- const leaderWinsVariance = leaderWins.reduce((sum, value) => sum + Math.pow(value - leaderWinsMean, 2), 0) / (leaderWins.length - 1);
94
+ const leaderWinsMean = leaderWins.reduce((sum, value) => sum + value, 0) / leaderWins.length
95
+ const leaderWinsVariance = leaderWins.reduce((sum, value) => sum + Math.pow(value - leaderWinsMean, 2), 0) / (leaderWins.length - 1)
96
96
  const leaderWinsStdev = Math.sqrt(leaderWinsVariance)
97
97
 
98
98
  // Calculate Interquartile Range (IQR)
@@ -125,7 +125,7 @@ const getGotchisSimNameFromTeam = (team) => {
125
125
 
126
126
  [0,1,2,3,4].forEach(i => {
127
127
  const gotchi = team.formation.back[i] || team.formation.front[i]
128
- const position = !!team.formation.back[i] ? 'B' : 'F'
128
+ const position = team.formation.back[i] ? 'B' : 'F'
129
129
 
130
130
  const nameParts = gotchi.name.split(' ')
131
131
  // Return e.g. "R|++++|1_B"
@@ -139,7 +139,7 @@ const runSims = async (simsVersion, gameLogicVersion, simsPerMatchup) => {
139
139
  const classCombos = require(`./${simsVersion}/class_combos.js`)
140
140
  const classTraitCombos = require(`./${simsVersion}/trait_combos.json`)
141
141
  const setTeamPositions = require(`./${simsVersion}/setTeamPositions`)
142
- const gameLogic = require("../../game-logic")[gameLogicVersion].gameLoop
142
+ const gameLogic = require('../../game-logic')[gameLogicVersion].gameLoop
143
143
 
144
144
  const attackingPowerLevels = ['Godlike']
145
145
  const defendingPowerLevels = ['Godlike', 'Mythical', 'Legendary']
@@ -181,7 +181,7 @@ const runSims = async (simsVersion, gameLogicVersion, simsPerMatchup) => {
181
181
 
182
182
  console.time(`Sims for ${attackingTeam.name}`)
183
183
 
184
- defendingTeamIndexes.forEach((defendingTeamIndex, i) => {
184
+ defendingTeamIndexes.forEach((defendingTeamIndex) => {
185
185
  const defendingTeam = createTeamFromTeamIndex(defendingTeamIndex, trainingGotchis, setTeamPositions)
186
186
 
187
187
  let matchupWins = 0
@@ -231,23 +231,16 @@ const runSims = async (simsVersion, gameLogicVersion, simsPerMatchup) => {
231
231
 
232
232
  if (process.env.CLOUD_RUN_JOB && process.env.SIMS_BUCKET) {
233
233
  // Save as JSON to GCS
234
- try {
235
- await storage.bucket(process.env.SIMS_BUCKET).file(`${process.env.CLOUD_RUN_EXECUTION}_${attackingTeamIndex}.json`).save(JSON.stringify(results))
236
- } catch (err) {
237
- throw err
238
- }
234
+ await storage.bucket(process.env.SIMS_BUCKET).file(`${process.env.CLOUD_RUN_EXECUTION}_${attackingTeamIndex}.json`).save(JSON.stringify(results))
239
235
 
240
236
  } else {
241
- console.log('Results', results)
237
+ console.log('Results', results)
242
238
 
243
239
  // Test saving to GCS
244
- if (false) {
240
+ const test = false
241
+ if (test) {
245
242
  process.env.GOOGLE_APPLICATION_CREDENTIALS = path.join(__dirname, '../../keyfile.json')
246
- try {
247
- await storage.bucket(process.env.SIMS_BUCKET).file(`avg-sims-znw68_${attackingTeamIndex}.json`).save(JSON.stringify(results))
248
- } catch (err) {
249
- throw err
250
- }
243
+ await storage.bucket(process.env.SIMS_BUCKET).file(`avg-sims-znw68_${attackingTeamIndex}.json`).save(JSON.stringify(results))
251
244
  }
252
245
  }
253
246
  }
@@ -70,7 +70,7 @@ module.exports = (team) => {
70
70
  const frontGotchis = team.formation.front.filter(gotchi => gotchi)
71
71
  if (frontGotchis.length === 5) {
72
72
  // Sort the gotchis by score in ascending order (lowest score first)
73
- const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader));
73
+ const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader))
74
74
 
75
75
  // Loop through the front row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the back
76
76
  let hasMoved = 0
@@ -88,7 +88,7 @@ module.exports = (team) => {
88
88
  const backGotchis = team.formation.back.filter(gotchi => gotchi)
89
89
  if (backGotchis.length === 5) {
90
90
  // Sort the gotchis by score in descending order (highest score first)
91
- const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader));
91
+ const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader))
92
92
 
93
93
  // Loop through the back row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the front
94
94
  let hasMoved = 0
@@ -87,7 +87,7 @@ module.exports = (team) => {
87
87
  const frontGotchis = team.formation.front.filter(gotchi => gotchi)
88
88
  if (frontGotchis.length === 5) {
89
89
  // Sort the gotchis by score in ascending order (lowest score first)
90
- const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader));
90
+ const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader))
91
91
 
92
92
  // Loop through the front row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the back
93
93
  let hasMoved = 0
@@ -105,7 +105,7 @@ module.exports = (team) => {
105
105
  const backGotchis = team.formation.back.filter(gotchi => gotchi)
106
106
  if (backGotchis.length === 5) {
107
107
  // Sort the gotchis by score in descending order (highest score first)
108
- const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader));
108
+ const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader))
109
109
 
110
110
  // Loop through the back row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the front
111
111
  let hasMoved = 0
@@ -87,7 +87,7 @@ module.exports = (team) => {
87
87
  const frontGotchis = team.formation.front.filter(gotchi => gotchi)
88
88
  if (frontGotchis.length === 5) {
89
89
  // Sort the gotchis by score in ascending order (lowest score first)
90
- const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader));
90
+ const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader))
91
91
 
92
92
  // Loop through the front row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the back
93
93
  let hasMoved = 0
@@ -105,7 +105,7 @@ module.exports = (team) => {
105
105
  const backGotchis = team.formation.back.filter(gotchi => gotchi)
106
106
  if (backGotchis.length === 5) {
107
107
  // Sort the gotchis by score in descending order (highest score first)
108
- const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader));
108
+ const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader))
109
109
 
110
110
  // Loop through the back row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the front
111
111
  let hasMoved = 0
@@ -87,7 +87,7 @@ module.exports = (team) => {
87
87
  const frontGotchis = team.formation.front.filter(gotchi => gotchi)
88
88
  if (frontGotchis.length === 5) {
89
89
  // Sort the gotchis by score in ascending order (lowest score first)
90
- const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader));
90
+ const orderedGotchis = JSON.parse(JSON.stringify(frontGotchis)).sort((a, b) => getFrontRowScore(a.id, team.leader) - getFrontRowScore(b.id, team.leader))
91
91
 
92
92
  // Loop through the front row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the back
93
93
  let hasMoved = 0
@@ -105,7 +105,7 @@ module.exports = (team) => {
105
105
  const backGotchis = team.formation.back.filter(gotchi => gotchi)
106
106
  if (backGotchis.length === 5) {
107
107
  // Sort the gotchis by score in descending order (highest score first)
108
- const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader));
108
+ const orderedGotchis = JSON.parse(JSON.stringify(backGotchis)).sort((a, b) => getFrontRowScore(b.id, team.leader) - getFrontRowScore(a.id, team.leader))
109
109
 
110
110
  // Loop through the back row and the first 2 gotchis that have a score of either orderedGotchis[0] or orderedGotchis[1] move to the front
111
111
  let hasMoved = 0
@@ -0,0 +1,87 @@
1
+ {
2
+ "formation": {
3
+ "front": [
4
+ null,
5
+ {
6
+ "id": 539,
7
+ "name": "Spider",
8
+ "enemyId": "SPIDER",
9
+ "speed": 200,
10
+ "health": 400,
11
+ "crit": 0,
12
+ "armor": 50,
13
+ "evade": 5,
14
+ "resist": 0,
15
+ "magic": 300,
16
+ "physical": 150,
17
+ "accuracy": 90,
18
+ "attack": "magic",
19
+ "specialId": 7,
20
+ "special": {
21
+ "id": 7,
22
+ "class": "Mage",
23
+ "name": "Thunder",
24
+ "cooldown": 2,
25
+ "leaderPassive": "Channel the coven"
26
+ }
27
+ },
28
+ null,
29
+ {
30
+ "id": 540,
31
+ "name": "Spider",
32
+ "enemyId": "SPIDER",
33
+ "speed": 200,
34
+ "health": 400,
35
+ "crit": 0,
36
+ "armor": 50,
37
+ "evade": 5,
38
+ "resist": 0,
39
+ "magic": 300,
40
+ "physical": 150,
41
+ "accuracy": 90,
42
+ "attack": "magic",
43
+ "specialId": 7,
44
+ "special": {
45
+ "id": 7,
46
+ "class": "Mage",
47
+ "name": "Thunder",
48
+ "cooldown": 2,
49
+ "leaderPassive": "Channel the coven"
50
+ }
51
+ },
52
+ null
53
+ ],
54
+ "back": [
55
+ null,
56
+ null,
57
+ {
58
+ "id": 541,
59
+ "name": "Spider",
60
+ "enemyId": "SPIDER",
61
+ "speed": 200,
62
+ "health": 400,
63
+ "crit": 0,
64
+ "armor": 50,
65
+ "evade": 5,
66
+ "resist": 0,
67
+ "magic": 300,
68
+ "physical": 150,
69
+ "accuracy": 90,
70
+ "attack": "magic",
71
+ "specialId": 7,
72
+ "special": {
73
+ "id": 7,
74
+ "class": "Mage",
75
+ "name": "Thunder",
76
+ "cooldown": 2,
77
+ "leaderPassive": "Channel the coven"
78
+ }
79
+ },
80
+ null,
81
+ null
82
+ ]
83
+ },
84
+ "leader": 540,
85
+ "name": "Dungeon Mob 1",
86
+ "owner": "0x10B989914A478Ed7DE2d2C4CC4e835bbd3de229b"
87
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "formation": {
3
+ "front": [
4
+ null,
5
+ {
6
+ "id": 1539,
7
+ "name": "Bat",
8
+ "enemyId": "BAT",
9
+ "speed": 200,
10
+ "health": 400,
11
+ "crit": 0,
12
+ "armor": 50,
13
+ "evade": 5,
14
+ "resist": 0,
15
+ "magic": 300,
16
+ "physical": 150,
17
+ "accuracy": 90,
18
+ "attack": "magic",
19
+ "specialId": 7,
20
+ "special": {
21
+ "id": 7,
22
+ "class": "Mage",
23
+ "name": "Thunder",
24
+ "cooldown": 2,
25
+ "leaderPassive": "Channel the coven"
26
+ }
27
+ },
28
+ null,
29
+ {
30
+ "id": 1540,
31
+ "name": "Bat",
32
+ "enemyId": "BAT",
33
+ "speed": 200,
34
+ "health": 400,
35
+ "crit": 0,
36
+ "armor": 50,
37
+ "evade": 5,
38
+ "resist": 0,
39
+ "magic": 300,
40
+ "physical": 150,
41
+ "accuracy": 90,
42
+ "attack": "magic",
43
+ "specialId": 7,
44
+ "special": {
45
+ "id": 7,
46
+ "class": "Mage",
47
+ "name": "Thunder",
48
+ "cooldown": 2,
49
+ "leaderPassive": "Channel the coven"
50
+ }
51
+ },
52
+ null
53
+ ],
54
+ "back": [
55
+ null,
56
+ null,
57
+ {
58
+ "id": 1541,
59
+ "name": "Bat",
60
+ "enemyId": "BAT",
61
+ "speed": 200,
62
+ "health": 400,
63
+ "crit": 0,
64
+ "armor": 50,
65
+ "evade": 5,
66
+ "resist": 0,
67
+ "magic": 300,
68
+ "physical": 150,
69
+ "accuracy": 90,
70
+ "attack": "magic",
71
+ "specialId": 7,
72
+ "special": {
73
+ "id": 7,
74
+ "class": "Mage",
75
+ "name": "Thunder",
76
+ "cooldown": 2,
77
+ "leaderPassive": "Channel the coven"
78
+ }
79
+ },
80
+ null,
81
+ null
82
+ ]
83
+ },
84
+ "leader": 1540,
85
+ "name": "Dungeon Mob 2",
86
+ "owner": "0x10B989914A478Ed7DE2d2C4CC4e835bbd3de229b"
87
+ }