Skip to content

Instantly share code, notes, and snippets.

@youz
Last active November 3, 2024 14:09
Show Gist options
  • Save youz/368f159701dfdbf56c25c04b8c1f0187 to your computer and use it in GitHub Desktop.
Save youz/368f159701dfdbf56c25c04b8c1f0187 to your computer and use it in GitHub Desktop.
shapeinfo.rb for Shapez2

shapeinfo.rb

MAMタイプと対応図形

  • ROS-MAM

    • ランダム図形#0
    • 結晶が含まれていない図形全て
  • CROS-MAM

    • ランダム図形#1
    • 結晶を含む図形のうち、以下の3条件を全て満たす物
      • 1層内に複数色の結晶がない
      • 結晶のある層に欠けがない
      • 結晶のある層より下に欠けやピンがない
  • CMAM

    • ヘキサゴナルを除く全シナリオのマイルストーンとタスクに登場する結晶を含む図形
    • CMAMは"結晶を扱う事のできるMAM"の事だが、このプログラムでは 東西南北に分割した1/4部位ごとにパーツを製造してスワップ機で仕上げるタイプのMAMを指す事とする
  • TMAM

    • CMAMのスワップ工程の後にさらに積層工程が必要な図形
      • ver.0.0.8時点ではクレイジーシナリオでも登場しない

使い方:

$ ruby shapeinfo.rb shapecode

$ ruby shapeinfo.rb 'RucbRucb'
CROS-MAM

$ ruby shapeinfo.rb 'RyRrRrRy:--cycy--:CwcycyCw:Cy----Cy:cw----cw'
CMAM (V)

$ ruby shapeinfo.rb 'cr------:Cg----Cg:cb--CbCb:CwCw----'
TMAM (H)
mask: RuRuRuRu:RuRuRuRu:RuRuCuCu:CuCuRuRu
   0: cr------:Cg----Cg:cb------
   1: ----CbCb
   2: CwCw----

$ ruby shapeinfo.rb 'CuCuCuCu:P-P-P-P-:crcrcrcr'
IMPOSSIBLE
class Shape
# 各レイヤーを7bit整数x4で表す
# 7bit整数1つでレイヤーの1/4部位の形状と色を表す
# ビット構成: RGBSSMM
# RGB : 色
# SS : 図形タイプ (素材がピンorクリスタルの場合00)
# 00 C
# 01 R
# 10 S
# 11 W
# MM : 素材タイプ
# 01 図形 (CRSW)
# 10 ピン (P)
# 11 結晶 (c)
attr_accessor :layers
def initialize(layers = [])
@layers = layers.map(&:dup)
drop!
end
def self.parse(shapecode)
# 図形コードからShapeを生成
s = Shape.new
s.layers = shapecode.split(':').map do |l|
if l.length != 8
raise "syntax error ('#{l}')"
end
l.scan(/../).map do |q|
case q
when /[CRSW][urgybmcw]/
t = 0b01 | ('CRSW'.index(q[0]) << 2)
when /P-/
t = 0b10
when /c[urgybmcw]/
t = 0b11
when '--'
t = 0
else
raise "illegal expression ('#{q}')"
end
c = 'urgybmcw-'.index(q[1]) & 0b111
c << 4 | t
end
end
s
end
def code
# 図形コードを生成
@layers.map { |l|
l.map { |q|
case q & 3
when 0
'--'
when 1
'CRSW'[(q >> 2) & 0b11] + 'urgybmcw'[q >> 4]
when 2
'P-'
when 3
'c' + 'urgybmcw'[q >> 4]
end
} * ''
} * ':'
end
def segments(layer_index)
# 指定レイヤーを水平方向に繋がっている部位ごとに分割し、配列として返す
# 各部位は位置番号の配列で表す
# ピンは全て単独で切り出す
# 例:
# Cu--Cu-- => [[0], [2]]
# P-CucrP- => [[0], [1, 2], [3]]
# P-P-P--- => [[0], [1], [2]]
# Cu--cgcb => [[0, 2, 3]]
l = @layers[layer_index].dup
segs = []
while l.any? { |q| q > 0 }
seg_start = l.index { |q| q > 0 }
if l[seg_start] & 1 == 1
# 基本図形 or 結晶
seg_end = seg_start
while l[seg_end + 1] & 1 == 1 && seg_end < 3
seg_end += 1
end
if seg_start == 0 && seg_end < 3
while l[seg_start - 1] & 1 == 1 && seg_start > -3
seg_start -= 1
end
end
else
# ピン
seg_end = seg_start
end
s = (seg_start..seg_end).map { |i| i % 4 }.sort
for i in s
l[i] = 0
end
segs << s
end
segs
end
def drop!(start_layer = 1)
# 宙に浮いている部位を落とす (切断や積層等の後処理用)
# 落ちた部位があればtrue, なければfalseを返す
# 結晶は壊さない
dropped = false
# iは落下部位がないか検査する層のindex
i = start_layer
while i < @layers.length
segments(i).each do |seg|
# jは落下先の層のindex
j = i
while j > 0
j -= 1
if seg.any? { |k| @layers[j][k] > 0 }
j += 1
break
end
end
next unless j < i
seg.each do |k|
@layers[j][k] = @layers[i][k]
@layers[i][k] = 0
end
dropped = true
end
i += 1
end
@layers.delete_if { |l| l.all?{ |q| q == 0 } }
dropped
end
def dup
Shape.new(@layers.map(&:dup))
end
def rotate(nquarter)
# 90*nquarter度回転した図形を返す
Shape.new(@layers.map { |l| l.rotate(nquarter) })
end
def stack(s)
# selfの上にsを積層した図形を返す (結晶は壊さない)
if @layers.empty?
s.dup
else
@layers.length
Shape.new(@layers.concat(s.layers))
# ns.layers = ns.layers.take(5)
end
end
def split
# 縦に切断した2つの図形と、左右それぞれで切断時に落下する部位があったかどうかを返す
# 返り値は 左shape, 左の落下有無(bool), 右shape, 右の落下有無(bool)
left = Shape.new
left.layers = @layers.map { |l| [0, 0, l[2], l[3]] }
right = Shape.new
right.layers = @layers.map { |l| [l[0], l[1], 0, 0] }
[left, left.drop!, right, right.drop!]
end
def has_crystal?
# 結晶があればtrueを返す
@layers.any? { |l| l.any? { |q| q & 3 == 3 } }
end
def impossible_crystal?
# 結晶を作る事ができない箇所に結晶があったらtrueを返す
# 結晶を作れない場所は
# ・隙間の直上
# ・図形or結晶の上にあるピンの上方
(0..3).any? do |i|
s = @layers.map { |l| 'bspc'[l[i] & 3] } * ''
s =~ /bc|[sc]+p.*c/
end
end
def ros?
# ランダム図形#0 (Randome Operator Shape #0) に出題されるタイプの図形か?
!has_crystal?
end
def cros?
# ランダム図形#1 (Randome Operator Shape #1) に出題されるタイプの図形か?
if !has_crystal?
return false
end
@layers.reverse.drop_while do |l|
# 結晶のある層より上の層をスキップ
l.all? { |q| q & 3 < 3 }
end.all? do |l|
if l.any? { |q| [0, 2].include?(q) }
# 欠けやピンがあったら×
false
else
# 結晶がある場合、層内の全ての結晶の色が同一でなければならない
c = l.find { |q| q & 3 == 3 }
if c
color = c >> 4
l.all? do |q|
if q & 3 == 3
q >> 4 == color
else
true
end
end
else
true
end
end
end
end
def swappable?
# スワップ機に通す時に落下する部位があるかどうか調べる
# 縦スワップと横スワップ(90度回転してからスワップ)の2パターンを調べ、
# それぞれの結果を配列にして返す
_, ldrop, _, rdrop = split
rots = rotate(1)
_, tdrop, _, bdrop = rots.split
[!(ldrop || rdrop), !(tdrop || bdrop)]
end
def unstack_for_tmam
# 図形をCMAMで作成可能な土台部分と後乗せする図形パーツに分割する
# また、土台部分切り出し用のマスキング図形を生成して返す
# CMAMだけで作成可能な場合は無加工の図形を返して終了
v, h = swappable?
if v || h
mask = Shape.new(@layers.map{ |l| [5, 5, 5, 5] })
return { base: dup, parts: [], mask: mask }
end
# 土台図形
bs = dup
# 後乗せパーツの配列
parts = []
# 上部に図形があるか?
covered = [false] * 4
# 実際の回路では図形信号から一部部位を削除しようとすると難しいので
# マスク用図形信号を生成する事で対応する
# 土台部分製造ラインで製造部位情報を読み出す際に、要求図形信号とマスク信号の&を取る
mask = []
# 最上層から下層に向かって後乗せパーツを分離して行く
i = bs.layers.length - 1
while i >= 1 && !covered.all?
# 結晶以外の部位で、上方から見えていてかつ直下から支えらている部位をマークする
# ピンの場合は必ず下から支えられている筈なので下層のチェックを省いて良い
sel = (0..3).map { |j|
m = bs.layers[i][j] & 3
!covered[j] && ((m == 1 && bs.layers[i-1][j] != 0) || m == 2)
}
# 上方から見えていてかつ横から支えられている部位(結晶を除く)をマークする
# 各部位の両隣の調査を2回繰り返せば全範囲の調査が完了する
2.times do
(0..3).each do |j|
if !sel[j]
m = bs.layers[i][j] & 3
sel[j] = !covered[j] && m == 1 && (sel[j-1] || sel[j+1])
end
end
end
# マスク情報を記録
mask << sel
# 後乗せ部位を分離してpartsに記録
if sel.any?
parts << Shape.new([(0..3).map { |j| sel[j] ? bs.layers[i][j] : 0 }])
# 土台図形の分離した部分を空間にする
(0..3).each do |j|
if sel[j]
bs.layers[i][j] = 0
end
covered[j] = covered[j] || (bs.layers[i][j] != 0)
end
if bs.layers[i].all? { |q| q == 0 }
bs.layers.delete_at(i)
end
end
i -= 1
end
# マスク情報を図形に変換
# 残す部分をRu(5), 除去する部分をCu(1)とする
m = c = Shape.parse('RuRuRuRu')
i.times do
m = m.stack(c)
end
mask.reverse.each do |l|
m = m.stack(Shape.new([l.map{ |b| b ? 1 : 5 }]))
end
{ base: bs, parts: parts.reverse, mask: m }
end
def impossible?
# 製造不可能な図形ならtrueを返す
if impossible_crystal?
return true
end
unstack_for_tmam => base:
v, h = base.swappable?
!v && !h
end
def show_mamtype
# 図形の製造に必要なMAMのタイプを表示する
if !has_crystal?
puts 'ROS-MAM'
elsif impossible_crystal?
puts 'IMPOSSIBLE'
elsif cros?
puts 'CROS-MAM'
else
v, h = swappable?
if v && h
puts 'CMAM'
elsif v ^ h
puts "CMAM (#{v ? 'V' : 'H'})"
else
unstack_for_tmam => { mask:, base:, parts: }
v, h = base.swappable?
if !v && !h
puts 'IMPOSSIBLE'
else
if v && h
puts 'TMAM'
elsif v ^ h
puts "TMAM (#{v ? 'V' : 'H'})"
end
puts "mask: #{mask.code}"
puts " 0: #{base.code}"
parts.each_with_index do |s, i|
puts " #{i+1}: #{s.code}"
end
end
end
end
end
end
if __FILE__ == $0
if ARGV.empty?
puts 'usage: ruby shapeinfo.rb SHAPECODE'
exit 1
end
s = Shape.parse(ARGV[0])
s.show_mamtype
end
require 'minitest/autorun'
require_relative 'shapeinfo'
class ShapeTests < Minitest::Test
def setup
@shapes_ros = [
'CuRuSuWu',
'CrP-CrP-:WwWw----:--SgSg--',
'CuCbRbCb:P-P-SwP-:P-P-P-P-:WrCr--Cr:SmCw--Cw' # task32-5
]
@shapes_cros = [
'crcrcrcr',
'cbcbcbcb:cgcgcgcg:crcrcrcr',
'RmRmRmRm:ccSwccSw:P---P---'
]
@shapes_cmam = [
'cmcmcm--', # task35-1
'RmCmWcCc:--Cu--Cu:RcCcCmCm:cwWucwWu', # Milestone9-6
'CucrcrCu:--CwCw--:----cc--:--CbCb--:--cw----', # task33-5
'RyRrRrRy:--cycy--:CwcycyCw:Cy----Cy:cw----cw' # task36-3
]
@shapes_tmam = [{
code: 'cr------:CwCw----:--CwCw--',
base: 'cr------',
parts: ['CwCw----', '--CwCw--']
}, {
code: 'Cu------:CuCu----:cgCwCw--:----CwCw',
base: 'Cu------:CuCu----:cg------',
parts: ['--CwCw--', '----CwCw']
}, {
code: 'Cu------:CuCu----:CuCwCw--:cb--CwCw',
base: 'Cu------:CuCu----:Cu------:cb------',
parts: ['--CwCw--', '----CwCw']
}, {
code: 'cr------:cg----Cu:cb--CwCw:CwCw----',
base: 'cr------:cg----Cu:cb------',
parts: ['----CwCw', 'CwCw----']
}]
@shapes_impossible = [
'Cu--Cu--:crcrcrcr',
'CuCuCuCu:P---P---:RuRuRuRu:cgcgcgcg',
'cr------:cgCu----:--cbCu--'
]
end
def test_parsing
[*@shapes_ros, *@shapes_cmam].each do |c|
s = Shape.parse(c)
assert_equal c, s.code
end
File.open('test-tasks-insane.txt', 'r') do |f|
f.each_line do |l|
if l !~ /#/
s = Shape.parse(l.chomp!)
assert_equal l, s.code
end
end
end
end
def test_segments
s = Shape.parse('Cu--Cu--:P-CucrP-:P-P-P---:Cu--cgcb')
assert_equal [[0], [2]], s.send(:segments, 0)
assert_equal [[0], [1, 2], [3]], s.send(:segments, 1)
assert_equal [[0], [1], [2]], s.send(:segments, 2)
assert_equal [[0, 2, 3]], s.send(:segments, 3)
end
def test_stack
l1 = Shape.parse('Cu------')
l2 = Shape.parse('P-RuRuP-')
l3 = Shape.parse('SuSuSuSu')
s = l1.stack(l2).stack(l3)
assert_equal 'CuRuRuP-:P-------:SuSuSuSu', s.code
end
def test_swappable
t = ->(c){ Shape.parse(c).swappable? }
assert_equal [true, true], t['CuCuCuCu']
assert_equal [true, false], t['Cu------:CuCu----']
assert_equal [false, true], t['CuCu----:CuCuCuCu']
assert_equal [false, false], t['CuCu----:--CuCu--:----CuCu']
end
def test_ros
@shapes_ros.each do |c|
s = Shape.parse(c)
assert s.ros?, "'#{c}' is a ros"
assert !s.cros?, "'#{c}' is not a cros"
end
@shapes_cros.each do |c|
s = Shape.parse(c)
assert !s.ros?, "'#{c}' is not a ros"
assert s.cros?, "'#{c}' is a cros"
end
@shapes_cmam.each do |c|
s = Shape.parse(c)
assert !s.cros?, "'#{c}' is not a cros"
end
end
def test_tmam
@shapes_tmam.each do |t|
t => { code:, base:, parts: }
s = Shape.parse(code)
result = s.unstack_for_tmam
assert !s.impossible?
assert_equal base, result[:base].code
assert_equal parts, result[:parts].map(&:code)
end
end
def test_impossible
@shapes_tmam.each do |t|
s = Shape.parse(t[:code])
assert !s.impossible?
end
@shapes_impossible.each do |c|
s = Shape.parse(c)
assert s.impossible?, "'#{c}' is impossible"
end
end
end
require_relative 'shapeinfo'
def test(filename)
puts "=== #{filename} ==="
File.open(filename, 'r') do |f|
f.each_line do |l|
if l[0] == '#'
puts l
else
l.chomp!
print l + ' -> '
Shape.parse(l).show_mamtype
end
end
end
end
test 'test-tasks-insane.txt'
test 'test-tmam.txt'
#8 Half-Ready
SuSuCrCr
SuSuCrCr:CrCrCuCu
SuSuCrCr:CrCrCuCu:SuSuCrCr
SuCuCuCr:CrCrCrCu:SuCuCuCr
#9 First Doubler
RbRuCrRu
RbRuCrRu:CuRbCuCr
RbRuCrRu:CuRbCuCr:CrRuCrCu
RbCrRbCr:CuCuCuCu:CrCrCrCr:CuCuCuCu
RuRuRuRu:RbCrRbCr:RuCuRuCu:RbCrRbCr
#10 Raised Stacking
CrCrCuCu:CuCu----
RbRbCuCu:CuCuCrCr
RbRb----:CuCuCrCr:CrCrCuCu
Rb--Rb--:CrCrCrCr:CuCuCuCu:CrCrCrCr
#11 Monochrome Spikers
Su--Su--:Cr--Cr--
Su--Su--:CrRuCrRu:--Rb--Rb
Su--Su--:CrRuCrRu:--Rb--Rb:SuSuSuSu
Su--Su--:CrCrCrCr:--Cu--Cu:SuSuSuSu
Rb--Rb--:RuRuRuRu:Rb--Rb--:SuSuSuSu
#12 Scrambled Specimen
CgWg----:Cu------
--Su----:CgWg----:CrWr----:Cu------
--SuSu--:CgWgWgCg:CrWrWrCr:Cu----Cu
Su--Su--:WgWgWgWg:--Su--Su:WrWrWrWr
Cg--Cg--:CrCgCrCg:CuCrCuCr:--Cu--Cu
#13 Navigator Badges
SuSu----:SrSb----
RrCb----:RuCu----:SuSu----:SrSb----
RrCbCbCb:RuCuCuCu:Su--Su--:Sr--Sb--
CbWbCbWb:CuWgCuWg:----Su--:----Sr--
RrWrCbWr:RuWgCuWg:Su------:Sb------
#14 Pushing the Limit
Rb--Rg--:Wu--Wu--
Rb--Rg--:WuWbWuWg:--Cu--Cu
Rb--Rg--:WuWbWuWg:SrCuSrCu:--Cr--Cr
Rb--Rg--:WuWbWuWg:SrCuSrCu:--Cr--Cr:WuCuWuCu
Rb--Rg--:WgWbWbWg:SrCgSrCb:--Cr--Cr:WuCuWuCu
#15 Starsight Ziggurat
WbWuWbWu
WbWuWbWu:--Wb--Wb:CuCuCuCu
WbWuWbWu:--Wb--Wb:RuCuRuCu:RrCrRrCr
WbWuWbWu:--Wb--Wb:RuCuRuCu:RrCrRrCr:CgCgCgCg
WbWgWbWg:--Wb--Wb:RuCgRuCg:RrCrRrCr:CgCgCgCg
#16 Space Bramble
SrSgSrSg
Sr--Sr--:WbSgWbSg:--Wu--Wu
Sr--Sr--:WbSgWbSg:--Wu--Wu:CbWbCbWb
Sr--Sr--:WbSgWbSg:--Wu--Wu:SrWbSrWb:WbWgWbWg
#17 Getting the Robot
Sb----Sb:WbWuWuWb
Sb----Sb:WbWuWuWb:CuSrSrCu:--CrCr--
Sb----Sb:WbWuWuWb:CuSrSrCu:CrCrCrCr:WgWgWgWg
Sr----Sr:WrWbWbWr:CbSrSrCb:CrCrCrCr:WgWgWgWg
#18 Galactic Gliders
Wr--Wr--:RuRuRuCu
Wr--Wr--:RuRuRuCu:WrCrWrCr:--Cu--Cu
WrRgWrSg:RuRuRuCu:WrCrWrCr:--Cu--Cu:CgCgCgCg
WrCrWrRr:RuCuRuRu:WrWrWrRr:CgWgCgRg
CgRgCgSg:CuRuCuCu:CrRrCrCr:RuRuRuCu:RgCgRgCg
#19 Pyramid Beacons
RbWuCuWu:--WbCbWb
RbWuCuWu:RuWbCbWb:RrWuCuWu:--WrCrWr
RuWbCbWb:RrWuCuWu:RuWrCrWr:RbWuCuWu
RrRrRrRr:RuRuRuRu:RbRbRbRb:RuRuRuRu:RrRrRrRr
WbWbCbWb:WuWuCuWu:WrWrCrWr:WuWuCuWu:WbWbCbWb
#20 Primitive Parasite
SrCgCgCg:WuCu--Cu
SrCgCgCg:WuCuWrCu:WrCrRgCr
SrCgCgCg:WuCuWrCu:WrCrRgCr:CgCgWbCg
SrCgCgCg:WuCuRuCu:WrCrWrCr:CgCgRgCg:RbCbWbCb
#21 Nova Sightseer
CuRuRuCu:--CwCw--
CyRyRyCy:CbCwCwCb
CyRyRyCy:CmCwCwCm:CbCbCbCb:Cm----Cm
CyRyRyCy:CmCwCwCm:CbCcCcCb:Cb----Cb:CmCbCbCm
#22 Grand-Doomed
SuSuSuSu:WrWrWrWr
SwSwSwSw:WrWrWrWr:CuCuCuCu
SwSwSwSw:WrWrWrWr:CmCmCmCm:WuWuWuWu
SwSwSwSw:WrWrWrWr:CmCmCmCm:WbWbWbWb:CgCgCgCg
#23 Suspicious Melding Ritual
--SbSb--:CbRbRbCb:Cw----Cw
--SySy--:CyRyRyCy:Cw----Cw
--SySy--:CyRyRySr:CwCw--Sr:------Wy
--SbSb--:SwRbRbSw:Cw----Cw
SySbSbSy:CwCwCwCw:RyRbRbCy:SwSrSrSw:Wy--Ry--
#24 Sight Beyond Colors
RuCu----:RwCw----
RuCuCmCm:RwCwCbCb
RrCrCmCm:RwCwCbCb:WyCyWyCy
RrCrRrCr:RwCwRwCw:CmCmCmCm:CbCbCbCb:WyCyWyCy
#25 Order of the Triad
CrCgCbCw
CrCgCbCw:CmCyCcCw
CrWrCrWr:CwWwCwWw:CmWmCmWm
RwCwCwCw:RgCgCgCg:RyCyCyCy
Sw--Sw--:WbCbWbCb:--Sw--Sw:CcWcCcWc
#26 Dress-up D'alien
P-P-P-P-:P-WgWgP-:Sg----Sg:Cg----Cg:P-----P-
P-P-P-P-:SrWgWgSr:CrP-P-Cr:CgRrRrCg:P-----P-
P-P-P-P-:SrWrWrSr:CrWuWuCr:CgRrRrCg:P-RwRwP-
P-WwWwP-:SrWmWmSr:CrRwRwCr:CgRuRuCg:P-P-P-P-
SmWwWwSm:CwWmWmCw:CcRwRwCc:P-RuRuP-:--P-P---
#27 Remote Observation
RrCwRrCw
RrCwRrCw:RwCuRwCu:--Cw--Cw
RrCwRrCw:RwCuRwCu:--Cw--Cw:CmCmCmCm:CcRcCcRc
RrCrRrCr:RwCcRwCc:Cc--Cc--:CyRyCyRy
CwCrCwCr:CuRcCuRc:Wc--Wc--:WmRmWmRm
#28 Entanglement Darter
P-P-P-P-
P-CwRwCw:CrP-P-P-
P-CwRwCw:CrP-P-P-:----Rr--:WwCwRwCw
P-CwRwCw:CrP-P-P-:--CrRrCr:WwCwRwCw:--P-P-P-
#29 Gravely Visions
WuRu----:CwWw----
WuRuRuWu:CwWwWwCw:P-----P-
WuRuRuWu:CyRyRyCy:CwWwWwCw:P-P-P-P-:--CrCr--
WuRuRyCy:Sw----Sw:CwWwWwCw:P-P-P-P-:--CrCr--
WwRyRwCy:Sr----Sr:CrWrWrCr:P-P-P-P-:--CwCw--
#30 Seasoned Driving
CbRcRcCb:Wu----Ru
CyRcRcCb:WrP-P-Rr:------Ru
CyRrRrCy:WwP-P-Rw:------Ru
CcRwRwCc:WrP-P-Rr:------Ru
CbRwRwCb:P-RrWrP-:SrRu--Sr:P-----P-:Sy----Sy
#31 Dimensional Whirler
SwP-SwP-:--P---P-:--Cw--Cw
RmCmRmCm:SwP-SwP-:--P---P-:--Cw--Cw:CcCcCcCc
RmP-RmP-:SwP-SwP-:CcP-CcP-:--Rc--Rc:RwCwRwCw
CmP-CmP-:P-CwP-Cw:P-CcP-Cc:CwP-CwP-:CcCwCcCw
#32 From Nothing to Rocket
CcCcRgCy:----Wu--:----P---:----P---:----Sm--
CyCcRgCc:SwP-WuP-:--P-P-P-:--CrP-Cr:----Sm--
CbCyRgCb:SwP-WuP-:P-P---P-:--Cr--Cr:--CwWrCw
CbCbRrCb:SwP-RyP-:P-P-ScP-:--Cr--Cr:--CwWrCw
CuCbRbCb:P-P-SwP-:P-P-P-P-:WrCr--Cr:SmCw--Cw
#33 It That Stared Back
CucrcrCu:--CuCu--
CucrcrCu:--CwCw--:--cbcb--
crcrcrcr:CwCwCwCw:cbcbcb--:--cc----
crcrcrcr:CwCwCwCw:cccccc--:CbCbCb--:--cw----
CucrcrCu:--CwCw--:----cc--:--CbCb--:--cw----
#34 Lightless Flash
CbRbRbRb:Cu--Cu--:----cc--:----Wu--
CbRbRbRb:P-P-CuP-:CuWcccWc:P---Wu--:Wc------
cyRbRbRb:P-P-CuP-:CwWcccWc:Cy--Wg--:Wc------
CbRbRbRb:cyP-CuP-:CwWcccWc:Cy--Wy--:Wc------
CbRbRbRb:--P-CuP-:CyWcccWc:cw--Wr--:Wg------
#35 Break it 'til you Make it
cmcmcm--
cmcmcm--:WuWuWuWu:cy--cycy
cmcmcm--:WuWuWuWu:cy--cycy:CwCwCwCw:cgcgcgcg
P-P-cmP-:WuWuWuWu:cy--cycy:CwCwCwCw:cgcgcgcg
P-P-cmP-:WuWuWuWu:cy--cy--:CwCwCwCw:cgcgcgcg
#36 Truth Behind Reality
RbRuRuRb:P-cbcbP-:P-----P-:P-----P-:Cr----Cr
RrRbRbRr:P-crcrP-:Cy----Cy:P-----P-:Cw----Cw
RyRrRrRy:--cycy--:CwcycyCw:Cy----Cy:cw----cw
RySrRySr:--Wb--Wb:CwWwCwWw:CyP-CyP-:cwCmcwCm
Rr--Rr--:cy--cy--:cyRwcyRw:--Cm--Cm:--cb--cb
cr------:CwCw----:--CwCw--
Cu------:CuCu----:Cwcg--Cw:----CwCw
Cu------:CuCu----:CuCwCw--:cb--CwCw
cr------:cg----Cu:cb--CwCw:CwCw----
cr------:cg----Cu:cb--CwCw:CwCw----:CwCwCwCw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment