Last active
January 30, 2019 03:51
-
-
Save gabrielflorit/7f370bc716aff805f593a3f80008711f to your computer and use it in GitHub Desktop.
SCRIPT-8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// title: platformer | |
// TODO: | |
// use sprites and map to draw tiles | |
// why am i drawing them via code?! | |
// clean up the gettiles / scanning code, it's atrocious | |
const rad2Deg = ø => ø * 180 / Math.PI | |
const tileTile = (a, b) => { | |
const r1RightEdgePastR2Left = a.x + 8 >= b.x | |
const r1LeftEdgePastR2Right = a.x <= b.x + 8 | |
const r1TopEdgePastR2Bottom = a.y + 8 >= b.y | |
const r1BottomEdgePastR2Top = a.y <= b.y + 8 | |
const collision = | |
r1RightEdgePastR2Left && | |
r1LeftEdgePastR2Right && | |
r1TopEdgePastR2Bottom && | |
r1BottomEdgePastR2Top | |
// If we had a collision, try to find the side. | |
if (collision) { | |
let side | |
const angle = rad2Deg(Math.atan2(b.y - a.y, a.x - b.x)) | |
if (angle > 45 && angle < 90 + 45) { | |
side = 'top' | |
} else { | |
side = 'other' | |
} | |
return side | |
} else { | |
return false | |
} | |
} | |
const getTileCoordsVertical = (d, offset) => { | |
const row = Math.ceil(Math.floor(d.y) / 8) + offset | |
const col = Math.floor(d.x / 8) | |
const onX = Math.floor(d.x) % 8 === 0 | |
return onX ? [[row, col]] : [[row, col], [row, col + 1]] | |
} | |
const getTileCoordsHorizontal = (d, offset) => { | |
const row = Math.ceil(Math.floor(d.y) / 8) | |
const col = Math.floor(d.x / 8) + offset | |
const onX = Math.floor(d.x) % 8 === 0 | |
const onY = Math.floor(d.y) % 8 === 0 | |
if (onX) { | |
return onY ? [[row, col]] : [[row - 1, col], [row, col]] | |
} else { | |
return onY ? [[row, col + 1]] : [[row - 1, col + 1], [row, col + 1]] | |
} | |
} | |
const getTileCoordsUnderneath = d => getTileCoordsVertical(d, 1) | |
const getTileCoordsOverhead = d => getTileCoordsVertical(d, -1) | |
const getTileCoordsToRight = d => getTileCoordsHorizontal(d, 1) | |
const getTileCoordsToLeft = d => getTileCoordsHorizontal(d, -1) | |
const coordsToTiles = (coords, roomNumber) => | |
coords.map(([row, col]) => rooms[roomNumber][row][col]) | |
const getTilesToLeft = (d, roomNumber) => | |
coordsToTiles(getTileCoordsToLeft(d), roomNumber) | |
const getTilesToRight = (d, roomNumber) => | |
coordsToTiles(getTileCoordsToRight(d), roomNumber) | |
const getTilesOverhead = (d, roomNumber) => | |
coordsToTiles(getTileCoordsOverhead(d), roomNumber) | |
const getTilesUnderneath = (d, roomNumber) => | |
coordsToTiles(getTileCoordsUnderneath(d), roomNumber) | |
const drawRoom = state => { | |
rooms[state.room].forEach((cols, rowNumber) => { | |
cols.forEach((cell, i) => { | |
sprite(i * 8, rowNumber * 8, cell, cell === 32 ? -3 : -1) | |
}) | |
}) | |
} | |
const sprites = { | |
mario: { | |
idle: [...range(21).map(d => 0), 7], | |
walk: [1, 2, 3, 4, 5, 6], | |
prejump: [8], | |
jump: [9], | |
fall: [10], | |
postfall: [8], | |
piping: [8] | |
}, | |
bowser: { | |
idle: [...range(10).map(d => 16), 17, ...range(10).map(d => 16)], | |
walk: [18, 19, 20, 19] | |
}, | |
coin: { | |
idle: [...range(40).map(d => 48), 49, 48, 50, 48, 49, 48, 50] | |
} | |
} | |
const rooms = [ | |
[ | |
[], | |
[32, 35, 36, ...range(13).map(i => 32)], | |
[32, 51, 52, ...range(12).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(12).map(i => null), ...range(3).map(i => 32)], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[...range(3).map(i => 32), ...range(12).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(12).map(i => null), 37, 38, 32], | |
[32, ...range(12).map(i => 32), 53, 54, 32] | |
], | |
[ | |
[], | |
[32, 35, 36, ...range(13).map(i => 32)], | |
[32, 51, 52, ...range(12).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[...range(3).map(i => 32), ...range(12).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(12).map(i => null), ...range(3).map(i => 32)], | |
[32, ...range(14).map(i => null), 32], | |
[32, ...range(12).map(i => null), 37, 38, 32], | |
[32, ...range(12).map(i => 32), 53, 54, 32] | |
] | |
] | |
const fsm = new StateMachine({ | |
init: 'idle', | |
transitions: [ | |
{ name: 'leftright', from: 'idle', to: 'walk' }, | |
{ name: 'noleftright', from: 'walk', to: 'idle' }, | |
{ name: 'a', from: 'idle', to: 'prejump' }, | |
{ name: 'a', from: 'walk', to: 'prejump' }, | |
{ name: 'launch', from: 'prejump', to: 'jump' }, | |
{ name: 'falling', from: 'jump', to: 'fall' }, | |
{ name: 'sinkholed', from: 'idle', to: 'fall' }, | |
{ name: 'sinkholed', from: 'walk', to: 'fall' }, | |
{ name: 'landed', from: 'fall', to: 'postfall' }, | |
{ name: 'bounce', from: 'fall', to: 'prejump' }, | |
{ name: 'recovered', from: 'postfall', to: 'idle' }, | |
{ name: 'die', from: 'idle', to: 'idle' }, | |
{ name: 'die', from: 'walk', to: 'idle' }, | |
{ name: 'die', from: 'prejump', to: 'idle' }, | |
{ name: 'die', from: 'jump', to: 'idle' }, | |
{ name: 'die', from: 'fall', to: 'idle' }, | |
{ name: 'die', from: 'postfall', to: 'idle' }, | |
{ name: 'pipe', from: 'idle', to: 'piping' }, | |
{ name: 'piped', from: 'piping', to: 'idle' } | |
] | |
}) | |
const e = { | |
mario: { | |
maxDx: 100 / 100, | |
maxDy: 4, | |
bounceBonus: 95 | |
} | |
} | |
const defaultMario = () => ({ | |
x: 8 + 4, | |
y: 8 * 2, | |
flip: false, | |
counter: 0, | |
dx: 0, | |
dy: 0, | |
mode: 'idle' | |
}) | |
const defaultBowser = () => ({ | |
x: 48, | |
y: 112, | |
dx: +0.5, | |
mode: 'walk', | |
flip: false, | |
counter: 0 | |
}) | |
const defaultGame = () => ({ | |
lives: 3, | |
coins: 0, | |
counter: 0, | |
room: 0 | |
}) | |
const defaultCoin = () => ({ | |
acquired: false, | |
counter: 0 | |
}) | |
const assignToObject = (object, properties) => { | |
Object.entries(properties).forEach(([key, value]) => { | |
object[key] = value | |
}) | |
} | |
const resetMario = mario => { | |
assignToObject(mario, defaultMario()) | |
} | |
const resetBowser = bowser => { | |
assignToObject(bowser, defaultBowser()) | |
} | |
const resetCoin = coin => { | |
assignToObject(coin, defaultCoin()) | |
} | |
const resetGame = state => { | |
assignToObject(state, defaultGame()) | |
resetMario(state.actors.find(d => d.name === 'mario')) | |
resetBowser(state.actors.find(d => d.name === 'bowser')) | |
resetCoin(state.actors.find(d => d.name === 'coin')) | |
} | |
initialState = { | |
mode: 'intro', | |
...defaultGame(), | |
actors: [ | |
{ | |
name: 'mario', | |
...defaultMario() | |
}, | |
{ | |
name: 'bowser', | |
start: 48, | |
end: 8 * 10, | |
...defaultBowser() | |
}, | |
{ | |
name: 'coin', | |
x: 8 * 13, | |
y: 8 * 8, | |
mode: 'idle', | |
...defaultCoin() | |
} | |
] | |
} | |
const moveHorizontally = ({ mario, input, state }) => { | |
const { maxDx } = e.mario | |
if (input.left) { | |
mario.dx = clamp(mario.dx - 0.5, -maxDx, maxDx) | |
mario.flip = true | |
} else if (input.right) { | |
mario.dx = clamp(mario.dx + 0.5, -maxDx, maxDx) | |
mario.flip = false | |
} else { | |
mario.dx = Math.sign(mario.dx) * Math.max(Math.abs(mario.dx) - 0.25, 0) | |
} | |
// Prevent mario from moving into a tile. | |
if (Math.floor(mario.x) % 8 === 0) { | |
if (mario.dx < 0) { | |
const tiles = getTilesToLeft(mario, state.room).filter(d => d) | |
if (tiles.length) { | |
mario.dx = 0 | |
} | |
} | |
if (mario.dx > 0) { | |
const tiles = getTilesToRight(mario, state.room).filter(d => d) | |
if (tiles.length) { | |
mario.dx = 0 | |
} | |
} | |
} | |
mario.x += mario.dx | |
} | |
const isOnGround = ({ state, mario }) => { | |
// If the y-coordinate isn't at a multiple of 8, | |
// we're obviously not on ground. | |
if (Math.floor(mario.y) % 8 !== 0) { | |
return false | |
} else { | |
// Try to get the one or two tiles underneath: | |
const tiles = getTilesUnderneath(mario, state.room) | |
// If we're exactly on one tile, | |
if (tiles.length === 1) { | |
// only check that one. | |
return !!tiles[0] | |
} else { | |
// If we're in between two tiles, at least one of them needs to be there. | |
return !!tiles[0] || !!tiles[1] | |
} | |
} | |
} | |
const moveBowser = ({ bowser, state }) => { | |
let nextMode = bowser.mode | |
if (bowser.mode === 'idle') { | |
state.counter % 6 === 0 && bowser.counter++ | |
if (bowser.counter > 20) { | |
nextMode = 'walk' | |
} | |
} | |
if (bowser.mode === 'walk') { | |
bowser.flip = bowser.dx < 0 | |
bowser.x += bowser.dx | |
if (bowser.x > bowser.end || bowser.x <= bowser.start) { | |
nextMode = 'idle' | |
bowser.dx *= -1 | |
} | |
state.counter % 6 === 0 && bowser.counter++ | |
} | |
if (bowser.mode !== nextMode) { | |
bowser.counter = 0 | |
} | |
bowser.mode = nextMode | |
} | |
const moveMario = ({ mario, input, state, bowser, coin }) => { | |
if (fsm.state === 'idle') { | |
moveHorizontally({ state, mario, input }) | |
state.counter % 6 === 0 && mario.counter++ | |
mario.isOnGround = isOnGround({ state, mario }) | |
!mario.isOnGround && fsm.can('sinkholed') && fsm.sinkholed() | |
if (input.left || input.right) { | |
fsm.can('leftright') && fsm.leftright() | |
} | |
if (input.a && fsm.can('a')) { | |
fsm.a() | |
playPhrase(1) | |
} | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
playPhrase(3) | |
--state.lives | |
// and reset mario. | |
resetMario(mario) | |
} | |
// Are we pressing down? | |
if (input.down) { | |
// And are we on the ground? | |
if (mario.isOnGround) { | |
// And are we above pipe tiles? | |
const tilesUnderneath = getTilesUnderneath(mario, state.room) | |
if ( | |
tilesUnderneath.length === 2 && | |
tilesUnderneath.filter(d => d === 37 || d === 38).length === 2 | |
) { | |
// And can we pipe? | |
if (fsm.can('pipe')) { | |
// Then pipe! | |
fsm.pipe() | |
playPhrase(4) | |
} | |
} | |
} | |
} | |
} | |
if (fsm.state === 'piping') { | |
mario.dy = 0.25 | |
mario.y += mario.dy | |
// If we get to the edge of the screen, | |
// reset the level. | |
if (mario.y > 112) { | |
fsm.can('piped') && fsm.piped() | |
if (state.room < rooms.length - 1) { | |
++state.room | |
resetMario(mario) | |
resetBowser(bowser) | |
resetCoin(coin) | |
} else { | |
state.mode = 'win' | |
} | |
} | |
} | |
if (fsm.state === 'walk') { | |
// Move horizontally. | |
moveHorizontally({ state, mario, input }) | |
// Increase counter. | |
state.counter % 4 === 0 && mario.counter++ | |
// Check if we're still on ground. | |
mario.isOnGround = isOnGround({ state, mario }) | |
// If we're not on ground, try firing `sinkholed` event. | |
!mario.isOnGround && fsm.can('sinkholed') && fsm.sinkholed() | |
// If we aren't pressing left or right, | |
if (!input.left && !input.right) { | |
// try firing `noleftright` event. | |
fsm.can('noleftright') && fsm.noleftright() | |
} | |
// If we're pressing `a`, and we can fire the `a` event, | |
if (input.a && fsm.can('a')) { | |
// fire it, | |
fsm.a() | |
// and play the jump phrase. | |
playPhrase(1) | |
} | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
--state.lives | |
playPhrase(3) | |
// and reset mario. | |
resetMario(mario) | |
} | |
} | |
if (fsm.state === 'prejump') { | |
moveHorizontally({ state, mario, input }) | |
mario.dy = | |
-e.mario.maxDy - | |
(mario.collidedWithBowser ? e.mario.bounceBonus / 100 : 0) | |
mario.counter++ | |
mario.counter === 2 && fsm.can('launch') && fsm.launch() | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
--state.lives | |
playPhrase(3) | |
// and reset mario. | |
resetMario(mario) | |
} | |
} | |
if (fsm.state === 'jump') { | |
moveHorizontally({ state, mario, input }) | |
const prevDy = mario.dy | |
// Decrease jump speed. | |
mario.dy = Math.min(mario.dy + 0.25, e.mario.maxDy) | |
// We can only move as far as the next tile. | |
// So, get the tiles overhead. | |
const tiles = getTilesOverhead(mario, state.room) | |
// If there are tiles, find the safe y distance to travel. | |
let safeDy | |
if (tiles.filter(d => d).length) { | |
safeDy = Math.max(-(mario.y % 8), mario.dy) | |
mario.dy = 0 | |
} else { | |
safeDy = mario.dy | |
} | |
mario.y += safeDy | |
if (prevDy < 0 && mario.dy >= 0) { | |
fsm.can('falling') && fsm.falling() | |
} | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
--state.lives | |
playPhrase(3) | |
// and reset mario. | |
resetMario(mario) | |
} | |
} | |
if (fsm.state === 'fall') { | |
moveHorizontally({ state, mario, input }) | |
// Increase fall speed. | |
mario.dy = Math.min(mario.dy + 0.25, e.mario.maxDy) | |
// We can only move as far as the next tile. | |
// So, get the tiles underneath. | |
const tiles = getTilesUnderneath(mario, state.room) // e.g. [room[row][col]] | |
// If there are tiles, find the safe y distance to travel. | |
const safeDy = tiles.filter(d => d).length ? 8 - mario.y % 8 : mario.dy | |
mario.y += Math.min(safeDy, mario.dy) | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, try firing the bounce state. | |
if (mario.collidedWithBowser === 'top' && fsm.can('bounce')) { | |
fsm.bounce() | |
playPhrase(2) | |
} | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
--state.lives | |
playPhrase(3) | |
// and reset mario. | |
resetMario(mario) | |
} | |
// Check if we're on the ground. | |
mario.isOnGround = isOnGround({ state, mario }) | |
// If we are, land. | |
mario.isOnGround && fsm.can('landed') && fsm.landed() | |
} | |
if (fsm.state === 'postfall') { | |
moveHorizontally({ state, mario, input }) | |
mario.dy = 0 | |
mario.counter++ | |
mario.counter === 3 && fsm.can('recovered') && fsm.recovered() | |
// Check if we're colliding with bowser. | |
mario.collidedWithBowser = tileTile(mario, bowser) | |
// If we are, fire the die event, | |
if (mario.collidedWithBowser === 'other' && fsm.can('die')) { | |
fsm.die() | |
--state.lives | |
playPhrase(3) | |
// and reset mario. | |
resetMario(mario) | |
} | |
} | |
if (!coin.acquired && tileTile(mario, coin)) { | |
++state.coins | |
coin.acquired = true | |
} | |
// If we changed states, | |
if (fsm.state !== mario.mode) { | |
// reset counter. | |
mario.counter = 0 | |
} | |
mario.mode = fsm.state | |
} | |
update = (state, input, elapsed) => { | |
if ( | |
state.mode === 'intro' || | |
state.mode === 'gameover' || | |
state.mode === 'win' | |
) { | |
if (input.start) { | |
resetGame(state) | |
state.mode = 'play' | |
} | |
} | |
if (state.mode === 'play') { | |
state.counter++ | |
const mario = state.actors.find(d => d.name === 'mario') | |
const bowser = state.actors.find(d => d.name === 'bowser') | |
const coin = state.actors.find(d => d.name === 'coin') | |
moveBowser({ bowser, state }) | |
moveMario({ mario, input, state, bowser, coin }) | |
state.counter % 5 === 0 && coin.counter++ | |
if (state.lives < 0) { | |
state.mode = 'gameover' | |
} | |
} | |
} | |
const drawActor = (actor, fade) => { | |
if (actor.name !== 'coin' || !actor.acquired) { | |
const cycle = sprites[actor.name][actor.mode] | |
sprite( | |
actor.x, | |
actor.y, | |
cycle[actor.counter % cycle.length], | |
fade ? -3 : 0, | |
actor.flip | |
) | |
} | |
// rectStroke(actor.x, actor.y, 8, 8, fade ? 3 : 0) | |
if (actor.name === 'mario') { | |
// if (actor.collidedWithBowser) { | |
// print(16, 16, `state: ${actor.mode}`, 0) | |
// print(16, 24, `collision side: ${actor.collidedWithBowser}`, 0) | |
// } | |
// const left = getTileCoordsToLeft(actor) | |
// rectStroke(left[1] * 8, left[0] * 8, 8, 8, 0) | |
// const right = getTileCoordsToRight(actor) | |
// right.forEach(d => { | |
// rectStroke(d[1] * 8, d[0] * 8, 8, 8, 0) | |
// }) | |
} | |
} | |
drawActors = (state, fade) => { | |
state.actors.forEach(actor => drawActor(actor, fade)) | |
} | |
draw = state => { | |
if (state.mode === 'intro') { | |
rectFill(0, 0, 128, 128, 6) | |
print(43, 47, 'platformer', 0) | |
print(42, 73, 'press start', 2) | |
print(33, 81, 'left / right / a', 4) | |
} | |
if (state.mode === 'play') { | |
clear() | |
// Draw lives. | |
sprite(0, 0, 0) | |
print(8 + 1, 0, state.lives.toString().padStart(2, '0'), 0) | |
// Draw coins. | |
sprite(8 * 3, 0, 48) | |
print(8 * 4 - 1, 0, state.coins.toString().padStart(2, '0'), 0) | |
rectFill(0, 5, 128, 3, 7) | |
drawActors(state) | |
drawRoom(state) | |
} | |
if (state.mode === 'gameover') { | |
rectFill(0, 56, 128, 24, 6) | |
print(46, 59, 'game over', 0) | |
print(42, 73, 'press start', 2) | |
} | |
if (state.mode === 'win') { | |
rectFill(0, 56, 128, 24, 6) | |
print(50, 59, 'you won', 0) | |
print(42, 73, 'press start', 2) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"0": [ | |
"0c00", | |
"15c00" | |
], | |
"1": [ | |
"0d27", | |
"1f27", | |
"2a#27" | |
], | |
"2": [ | |
"0g27", | |
"1b27", | |
"2d37" | |
], | |
"3": [ | |
"0b27", | |
"1g#27", | |
"2f27", | |
"3d27", | |
"4b17", | |
"5g#17", | |
"6f17", | |
"7d17" | |
], | |
"4": [ | |
"0b37", | |
"1a37", | |
"2g37", | |
"3f37", | |
"4d#37", | |
"5c#37", | |
"6b27", | |
"7a27", | |
"8g27", | |
"9f27", | |
"10d#27", | |
"11c#27", | |
"12b17", | |
"13a17", | |
"14g17", | |
"15f17" | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"0": [ | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
], | |
[ | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null, | |
null | |
] | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"0": [ | |
" 2220 ", | |
" 22222", | |
" 20270 ", | |
" 200220", | |
" 2000 ", | |
" 221331 ", | |
"0 333351", | |
" 2 3 " | |
], | |
"1": [ | |
" 2220 ", | |
" 22222", | |
" 20270 ", | |
" 200220", | |
" 2000 ", | |
" 22135 ", | |
" 20335 ", | |
" 223 " | |
], | |
"2": [ | |
" 2222 ", | |
" 22222", | |
" 22027 ", | |
" 220022", | |
" 2200 ", | |
" 32215 ", | |
" 33220 ", | |
" 2 3 " | |
], | |
"3": [ | |
" 2222 ", | |
" 22222", | |
" 22027 ", | |
" 220022", | |
" 2200 ", | |
" 322150", | |
" 233322 ", | |
" 3 " | |
], | |
"4": [ | |
" 2220 ", | |
" 22222", | |
" 20270 ", | |
" 200220", | |
" 2000 ", | |
" 22135 ", | |
" 20335 ", | |
" 223 " | |
], | |
"5": [ | |
" 2202 ", | |
" 22222", | |
" 02707 ", | |
" 002202", | |
" 0000 ", | |
" 221331 ", | |
"0 333351", | |
" 3 2 " | |
], | |
"6": [ | |
" 2202 ", | |
" 22222", | |
" 02707 ", | |
" 002202", | |
" 220000 ", | |
"0 213310", | |
" 333335 ", | |
" 2 " | |
], | |
"7": [ | |
" 2220 ", | |
" 22222", | |
" 20200 ", | |
" 200220", | |
" 2000 ", | |
" 221331 ", | |
"0 333351", | |
" 2 3 " | |
], | |
"8": [ | |
" ", | |
" 2220 ", | |
" 22222", | |
" 20270 ", | |
" 200220", | |
" 222000 ", | |
"0 333351", | |
" 2 3 " | |
], | |
"9": [ | |
" 2220 ", | |
" 222221", | |
" 2027072", | |
" 2002202", | |
" 220001 ", | |
"0 21335 ", | |
" 33353 ", | |
" 2 " | |
], | |
"10": [ | |
" 20 ", | |
" 222221", | |
" 2222 2", | |
" 20270 2", | |
" 200220 ", | |
"0220001 ", | |
" 213353", | |
" 23335 " | |
], | |
"16": [ | |
" 022 3 ", | |
" 5047000", | |
"05200000", | |
"5120022 ", | |
"01710001", | |
"52710171", | |
" 110021 ", | |
" 11 21 " | |
], | |
"17": [ | |
" 033 3 ", | |
" 5022000", | |
"05200000", | |
"5120022 ", | |
"01710001", | |
"52710171", | |
" 110021 ", | |
" 11 21 " | |
], | |
"18": [ | |
" 022 3 ", | |
" 5047000", | |
"05200000", | |
"5120022 ", | |
"0117100 ", | |
"552711 ", | |
" 110021 ", | |
" 11 21 " | |
], | |
"19": [ | |
" 022 3 ", | |
" 5047000", | |
"05200000", | |
"5120022 ", | |
"0171000 ", | |
"5271071 ", | |
" 1102 ", | |
" 1121 " | |
], | |
"20": [ | |
" 022 3 ", | |
" 5047000", | |
"05200000", | |
"5120022 ", | |
"17100001", | |
"27100171", | |
" 211 ", | |
" 211 " | |
], | |
"32": [ | |
"00112112", | |
"02225223", | |
"12225225", | |
"12223225", | |
"13552112", | |
"01121223", | |
"12231225", | |
"25532555" | |
], | |
"33": [ | |
"11111114", | |
"14444445", | |
"14445445", | |
"14545445", | |
"54555455", | |
"55522553", | |
"15231525", | |
"25532555" | |
], | |
"35": [ | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044" | |
], | |
"36": [ | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 " | |
], | |
"37": [ | |
"50000004", | |
"54000445", | |
"54000445", | |
"54000445", | |
"54000445", | |
"54000445", | |
"55555555", | |
" 5544455" | |
], | |
"38": [ | |
"44440000", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55555555", | |
"5555535 " | |
], | |
"48": [ | |
" 000 ", | |
" 00100 ", | |
" 00100 ", | |
" 00100 ", | |
" 000 ", | |
" ", | |
" ", | |
" " | |
], | |
"49": [ | |
" 110 ", | |
" 110 ", | |
" 110 ", | |
" 110 ", | |
" 110 ", | |
" ", | |
" ", | |
" " | |
], | |
"50": [ | |
" 011 ", | |
" 011 ", | |
" 011 ", | |
" 011 ", | |
" 011 ", | |
" ", | |
" ", | |
" " | |
], | |
"51": [ | |
" 5400044", | |
"40000004", | |
"54000445", | |
"54000445", | |
"54000445", | |
"54000445", | |
"54000445", | |
"55555555" | |
], | |
"52": [ | |
"5553303 ", | |
"44440000", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55553303", | |
"55555555" | |
], | |
"53": [ | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044", | |
" 5400044" | |
], | |
"54": [ | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 ", | |
"5553303 " | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment