-
Notifications
You must be signed in to change notification settings - Fork 0
/
roka_bu.p8
1096 lines (967 loc) · 41 KB
/
roka_bu.p8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
pico-8 cartridge // http://www.pico-8.com
version 16
__lua__
snd=
{
jump=24,
pickup=23,
death=25
}
--music tracks
mus=
{
0
}
startscreen=true
waiting=true
goal=nil
dead=false
win=false
waiting = false
water={}
function trigger_death()
sfx(snd.death,3)
local dpal={0,1,1, 2,1,13,6,
4,4,9,3, 13,1,13,14}
for i=0,40 do
for j=1,15 do
col = j
for k=1,((i+(j%5))/4) do
col=dpal[col]
end
pal(j,col,1)
end
flip()
end
waiting = true
cls(0)
pal()
print("you are dead", 30, 40)
print("press 'c' to restart", 30, 60)
end
function trigger_win()
cls(0)
print("you won", 30, 40)
print("score: "..p1.coins, 30, 60)
print("press 'c' to restart", 30, 100)
waiting=true
end
--point to box intersection.
function intersects_point_box(px,py,x,y,w,h)
if flr(px)>=flr(x) and flr(px)<flr(x+w) and
flr(py)>=flr(y) and flr(py)<flr(y+h) then
return true
else
return false
end
end
--box to box intersection
function intersects_box_box(
x1,y1,
w1,h1,
x2,y2,
w2,h2)
local xd=x1-x2
local xs=w1*0.5+w2*0.5
if abs(xd)>=xs then return false end
local yd=y1-y2
local ys=h1*0.5+h2*0.5
if abs(yd)>=ys then return false end
return true
end
--check if pushing into side tile and resolve.
--requires self.dx,self.x,self.y, and
--assumes tile flag 0 == solid
--assumes sprite size of 8x8
function collide_side(self)
local offset=self.w/3
for i=-(self.w/3),(self.w/3),2 do
--if self.dx>0 then
if fget(mget((self.x+(offset))/8,(self.y+i)/8),0) then
self.dx=0
self.x=(flr(((self.x+(offset))/8))*8)-(offset)
return true
end
--elseif self.dx<0 then
if fget(mget((self.x-(offset))/8,(self.y+i)/8),0) then
self.dx=0
self.x=(flr((self.x-(offset))/8)*8)+8+(offset)
return true
end
-- end
end
--didn't hit a solid tile.
return false
end
function collide_pickups(self)
for i=-(self.w/3),(self.w/3),2 do
local tile=mget((self.x+i)/8,(self.y+(self.h/2))/8)
if fget(tile, 5) then
sfx(snd.pickup,3)
mset((self.x+i)/8,(self.y+(self.h/2))/8,0)
self.coins= self.coins +1
elseif goal != nil and intersects_box_box(
self.x-self.w/2,
self.y-self.h/2,
self.w,
self.h,
goal.x-4,
goal.y-4,
8,8 ) then
win=true
end
end
end
function collide_enemy(self)
for k,e in pairs(enemies) do
if intersects_box_box(
self.x-self.w*0.45,
self.y-self.h*0.2,
self.w*.8,
self.h*.8,
e.x,e.y,e.w,e.h ) then
if self.dy > 0 and not e.dieing then
e:die()
sfx(22,3)
p1.dy= -2
p1.djump_spent=false
else
if not e.dieing then
dead=true
end
end
end
end
end
--check if pushing into floor tile and resolve.
--requires self.dx,self.x,self.y,self.grounded,self.airtime and
--assumes tile flag 0 or 1 == solid
function collide_floor(self)
--only check for ground when falling.
if self.dy<0 then
return false
end
local landed=false
--check for collision at multiple points along the bottom
--of the sprite: left, center, and right.
for i=-(self.w/3),(self.w/3),2 do
local tile=mget((self.x+i)/8,(self.y+(self.h/2))/8)
if fget(tile,0) or (fget(tile,1) and self.dy>=0) then
self.dy=0
self.y=(flr((self.y+(self.h/2))/8)*8)-(self.h/2)
self.grounded=true
self.airtime=0
landed=true
end
end
return landed
end
--check if pushing into roof tile and resolve.
--requires self.dy,self.x,self.y, and
--assumes tile flag 0 == solid
function collide_roof(self)
--check for collision at multiple points along the top
--of the sprite: left, center, and right.
for i=-(self.w/3),(self.w/3),2 do
if fget(mget((self.x+i)/8,(self.y-(self.h/2))/8),0) then
self.dy=0
self.y=flr((self.y-(self.h/2))/8)*8+8+(self.h/2)
self.jump_hold_time=0
end
end
end
--make 2d vector
function m_vec(x,y)
local v=
{
x=x,
y=y,
--get the length of the vector
get_length=function(self)
return sqrt(self.x^2+self.y^2)
end,
--get the normal of the vector
get_norm=function(self)
local l = self:get_length()
return m_vec(self.x / l, self.y / l),l;
end,
}
return v
end
--square root.
function sqr(a) return a*a end
--round to the nearest whole number.
function round(a) return flr(a+0.5) end
--utils
--------------------------------
--print string with outline.
function printo(str,startx,
starty,col,
col_bg)
print(str,startx+1,starty,col_bg)
print(str,startx-1,starty,col_bg)
print(str,startx,starty+1,col_bg)
print(str,startx,starty-1,col_bg)
print(str,startx+1,starty-1,col_bg)
print(str,startx-1,starty-1,col_bg)
print(str,startx-1,starty+1,col_bg)
print(str,startx+1,starty+1,col_bg)
print(str,startx,starty,col)
end
--print string centered with
--outline.
function printc(
str,x,y,
col,col_bg,
special_chars)
local len=(#str*4)+(special_chars*3)
local startx=x-(len/2)
local starty=y-2
printo(str,startx,starty,col,col_bg)
end
--objects
function m_water(x,y,tile)
local w={
x=x,
y=y,
w=8,
h=8,
anims=
{
["stand"]=
{
ticks=18,
frames={tile,tile+1},
}
},
curanim="stand",
curframe=1,
animtick=0,
flipx=false, -- right
tick = 0,
update=function(self)
self.animtick-=1
if self.animtick<=0 then
if self.dieing then
for k,v in pairs(enemies) do
if v == self then
enemies[k] = nil
end
end
end
self.curframe+=1
local a=self.anims[self.curanim]
self.animtick=a.ticks--reset timer
if self.curframe>#a.frames then
self.curframe=1--loop
end
end
end,
draw=function(self)
local a=self.anims[self.curanim]
local frame=a.frames[self.curframe]
spr(frame,
self.x,
self.y,
1,1,
self.flipx,
false)
end,
}
return w
end
--------------------------------
-- make enemy
function m_enemy(x,y, tile)
local e= {
x=x,
y=y,
w=8,
h=8,
anims=
{
["stand"]=
{
ticks=18,
frames={tile,tile+1},
},
["die"]={
ticks=200,
frames={tile+2}
},
},
curanim="stand",
curframe=1,
animtick=0,
flipx=false, -- right
tick = 0,
dieing=false,
move=function(self)
if self.dieing then
return
end
local xo=1
if self.flipx then
xo=-1
end
local tile=mget((self.x+5*xo)/8,((self.y+7)/8)+1)
local tile1=mget((self.x+5*xo)/8,(self.y+7)/8)
if self.flipx then
self.x-=1
else
self.x+=1
end
if not (fget(tile,0) or fget(tile,1) ) or fget(tile1, 0) then
self.flipx = not self.flipx
end
end,
update=function(self)
self.animtick-=1
if self.animtick<=0 then
if self.dieing then
self.dieing = false
self.curanim = "stand"
end
self.curframe+=1
local a=self.anims[self.curanim]
self.animtick=a.ticks--reset timer
if self.curframe>#a.frames then
self.curframe=1--loop
end
end
end,
draw=function(self)
local a=self.anims[self.curanim]
local frame=a.frames[self.curframe]
spr(frame,
self.x,
self.y,
1,1,
self.flipx,
false)
end,
die=function(self)
self.curanim="die"
self.dieing=true
self.curframe=1
self.animtick=self.anims.die.ticks
end
}
return e
end
--make the player
function m_player(x,y)
--todo: refactor with m_vec.
local p=
{
x=x,
y=y,
dx=0,
dy=0,
w=16,
h=16,
max_dx=1,--max x speed
max_dy=2,--max y speed
jump_speed=-1.75,--jump veloclity
acc=0.05,--acceleration
dcc=0.75,--decceleration
air_dcc=.98,--air decceleration
grav=0.15,
coins = 0,
--helper for more complex
--button press tracking.
--todo: generalize button index.
jump_button=
{
update=function(self)
--start with assumption
--that not a new press.
self.is_pressed=false
if btn(5) then
if not self.is_down then
self.is_pressed=true
end
self.is_down=true
self.ticks_down+=1
else
self.is_down=false
self.is_pressed=false
self.ticks_down=0
end
end,
--state
is_pressed=false,--pressed this frame
is_down=false,--currently down
ticks_down=0,--how long down
},
jump_hold_time=0,--how long jump is held
min_jump_press=5,--min time jump can be held
max_jump_press=15,--max time jump can be held
jump_btn_released=true,--can we jump again?
grounded=false,--on ground
djump_spent=false,
airtime=0,--time since grounded
--animation defions.
--use with set_anim()
anims=
{
["stand"]=
{
ticks=18,--how long is each frame shown.
frames={1,3},--what frames are shown.
},
["walk"]=
{
ticks=5,
frames={33,35,37,39},
},
["jump_start"]=
{
ticks=24,
frames={41},
},
["jump_up"]=
{
ticks=8,
frames={43},
},
["fall"]=
{
ticks=8,
frames={45},
},
["slide"]=
{
ticks=4,
frames={35},
},
},
curanim="walk",--currently playing animation
curframe=1,--curent frame of animation.
animtick=0,--ticks until next frame should show.
flipx=false,--show sprite be flipped.
--request new animation to play.
set_anim=function(self,anim)
if(anim==self.curanim)return--early out.
local a=self.anims[anim]
self.animtick=a.ticks--ticks count down.
self.curanim=anim
self.curframe=1
end,
--call once per tick.
update=function(self)
--todo: kill enemies.
--pickups
collide_pickups(self)
collide_enemy(self)
--track button presses
local bl=btn(0) --left
local br=btn(1) --right
--move left/right
if bl==true then
self.dx-=self.acc
br=false--handle double press
elseif br==true then
self.dx+=self.acc
else
if self.grounded then
self.dx*=self.dcc
else
self.dx*=self.air_dcc
end
end
--limit walk speed
self.dx=mid(-self.max_dx,self.dx,self.max_dx)
--move in x
self.x+=self.dx
--hit walls
collide_side(self)
--jump buttons
self.jump_button:update()
if self.djump_spent and self.grounded then
self.djump_spent = false
end
--jump is complex.
--we allow jump if:
-- on ground
-- recently on ground
-- pressed btn right before landing
--also, jump velocity is
--not instant. it applies over
--multiple frames.
if self.jump_button.is_down then
--is player on ground recently.
--allow for jump right after
--walking off ledge.
-- if self.grounded or self.airtime<5 then
-- local on_ground=true
-- elseif not self.djump_spent then
-- local on_ground = true
-- self.djump_spent = true
-- else
-- local on_ground = false
-- end
local on_ground = (self.grounded or self.airtime < 5)
--was btn presses recently?
--allow for pressing right before
--hitting ground.
local new_jump_btn=self.jump_button.ticks_down<10
--is player continuing a jump
--or starting a new one?
if (not on_ground and not self.djump_spent and self.jump_button.ticks_down==1) then
self.djump_spent = true
on_ground = true
end
if self.jump_hold_time>0 or (on_ground and new_jump_btn) then
if(self.jump_hold_time==0)sfx(snd.jump,2)--new jump snd
self.jump_hold_time+=1
--keep applying jump velocity
--until max jump time.
if self.jump_hold_time<self.max_jump_press then
self.dy=self.jump_speed--keep going up while held
end
end
else
self.jump_hold_time=0
end
--move in y
self.dy+=self.grav
self.dy=mid(-self.max_dy,self.dy,self.max_dy)
self.y+=self.dy
--floor
if not collide_floor(self) then
if self.dy < 0 then
self:set_anim("jump_up")
else
self.dy = self.dy*1.5
self:set_anim("fall")
end
self.grounded=false
self.airtime+=1
end
--roof
collide_roof(self)
--handle playing correct animation when
--on the ground.
if self.grounded then
if br then
if self.dx<0 then
--pressing right but still moving left.
self:set_anim("slide")
else
self:set_anim("walk")
end
elseif bl then
if self.dx>0 then
--pressing left but still moving right.
self:set_anim("slide")
else
self:set_anim("walk")
end
else
self:set_anim("stand")
end
end
--flip
if br then
self.flipx=false
elseif bl then
self.flipx=true
end
--anim tick
self.animtick-=1
if self.animtick<=0 then
self.curframe+=1
local a=self.anims[self.curanim]
self.animtick=a.ticks--reset timer
if self.curframe>#a.frames then
self.curframe=1--loop
end
end
end,
--draw the player
draw=function(self)
if self.x<8 then
self.x = 8
elseif self.x>1016 then
self.x=1016
end
if self.y>128 then
dead=true
elseif self.y<-5 then
self.y=-5
end
local a=self.anims[self.curanim]
local frame=a.frames[self.curframe]
spr(frame,
self.x-(self.w/2),
self.y-(self.h/2),
self.w/8,self.h/8,
self.flipx,
false)
end,
}
return p
end
--make the camera.
function m_cam(target)
local c=
{
tar=target,--target to follow.
pos=m_vec(target.x,target.y),
--how far from center of screen target must
--be before camera starts following.
--allows for movement in center without camera
--constantly moving.
pull_threshold=16,
--min and max positions of camera.
--the edges of the level.
pos_min=m_vec(64,64),
pos_max=m_vec(960,64),
shake_remaining=0,
shake_force=0,
update=function(self)
self.shake_remaining=max(0,self.shake_remaining-1)
--follow target outside of
--pull range.
if self:pull_max_x()<self.tar.x then
self.pos.x+=min(self.tar.x-self:pull_max_x(),4)
end
if self:pull_min_x()>self.tar.x then
self.pos.x+=min((self.tar.x-self:pull_min_x()),4)
end
if self:pull_max_y()<self.tar.y then
self.pos.y+=min(self.tar.y-self:pull_max_y(),4)
end
if self:pull_min_y()>self.tar.y then
self.pos.y+=min((self.tar.y-self:pull_min_y()),4)
end
--lock to edge
if(self.pos.x<self.pos_min.x)self.pos.x=self.pos_min.x
if(self.pos.x>self.pos_max.x)self.pos.x=self.pos_max.x
if(self.pos.y<self.pos_min.y)self.pos.y=self.pos_min.y
if(self.pos.y>self.pos_max.y)self.pos.y=self.pos_max.y
end,
cam_pos=function(self)
--calculate camera shake.
local shk=m_vec(0,0)
if self.shake_remaining>0 then
shk.x=rnd(self.shake_force)-(self.shake_force/2)
shk.y=rnd(self.shake_force)-(self.shake_force/2)
end
return self.pos.x-64+shk.x,self.pos.y-64+shk.y
end,
pull_max_x=function(self)
return self.pos.x+self.pull_threshold
end,
pull_min_x=function(self)
return self.pos.x-self.pull_threshold
end,
pull_max_y=function(self)
return self.pos.y+self.pull_threshold
end,
pull_min_y=function(self)
return self.pos.y-self.pull_threshold
end,
shake=function(self,ticks,force)
self.shake_remaining=ticks
self.shake_force=force
end
}
return c
end
--game flow
--------------------------------
--reset the game to its initial
--state. use this instead of
--_init()
function reset()
ticks=0
enemies = {}
p1=m_player(20,40)
p1:set_anim("walk")
cam=m_cam(p1)
music(0)
end
function move_actors()
for x=p1.x/8-5, p1.x/8+5 do
for y=0, 32 do
local tile=mget(x,y)
if fget(tile, 7) then
mset(x,y, 0)
add(enemies, m_enemy(x*8,y*8,tile))
elseif fget(tile, 2) then
mset(x,y, 0)
t=m_water(x*8,y*8,tile)
if fget(tile, 6) then
goal=t
end
add(water, t)
end
end
end
for k,e in pairs(enemies) do
if flr(rnd(5)) ==1 then
e:move()
end
end
end
--p8 functions
--------------------------------
function _init()
reset()
end
function _update60()
if btn(5) and btn(4) then
run()
elseif( dead or win )and btn(4) then
run()
end
ticks+=1
p1:update()
cam:update()
for k,e in pairs(enemies) do
e:update()
end
for k,e in pairs(water) do
e:update()
end
move_actors()
end
function juggle(tilex, tiley, posy, height,offset)
local os=offset*cam:cam_pos()
local n=flr(os/192)
map(tilex,tiley,n*192-os,posy,24,height)
map(tilex,tiley,(n+1)*192-os,posy,24,height)
end
function _draw()
if startscreen then
cls(0)
print("jump with 'x'", 10, 20, 9)
print("move with ⬅️ and ➡️", 10, 40, 9)
print("find the pupy", 10, 60, 9)
print("press x to start", 10, 90, 9)
if btn(5) then
startscreen = false
waiting = false
end
elseif waiting then
return
elseif dead then
trigger_death()
elseif win then
trigger_win()
return
else
progress=1
--clear the screen with black
cls(0)
--set the sky color: pink
rectfill(0,0, 128, 60, 14)
--draw mountains bg
juggle(24,16,0, 6,progress*.1)
-- --draw midleground
juggle(0,22, 10,7,progress*.2)
--draw trees
palt(15, true)
palt(0, false)
juggle(0,16, 20, 6,progress*.5)
palt(15, false)
palt(0, true)
-- draw the level
camera(cam:cam_pos())
map(0,0,0,0,128,128)
p1:draw()
for k,e in pairs(enemies ) do
e:draw()
end
for k,w in pairs(water ) do
w:draw()
end
--hud
camera(0,0)
print(p1.coins ,64,4,7,0,0)
end
end
__gfx__
00000000000000000000000000007000000000007700000077000000000000000000000000000000000000000000000000000000000000000000000000777700
0000000067000000000000000007700000000000900900900900000000000000009f00f9009f00f90000000000000000000a0000000e00000008000009a99a70
007007006770000000000000006770000000000090099990090900900000000000ffffff00ffffff00000000000000000057a000001fe000001f8000aa7aa7a9
000770006770000000000000066770000070070090098989090999900000000000f8fff800f8fff800000000000000000a57aa00011fee00011f88000a999a90
00077000d777000000700700d77770000670076090099190900989890009009090fff2ff90fff2ff00f7007f000000000059a0000015e0000015800000a9a900
00700700d777000006700760d77770000d7777d09999970099999190099999900ffff2f00ffffff00077777700000000000500000001000000010000000a9000
00000000277770000d7777d027777000677777700999770009997700099989890fffff000fffff00ff7b777b0000000000000000000000000000000000000000
00000000267770006777777026777000771771770907090009074090790991900f490f000f490f00f79779770000000000000000000000000000000000000000
88888888006700007717717700670000777777770000000000f7007f000000007700000077000000000000000000000000000000000000000070070000000000
888888880006d76d777777770006d76d6775777000f7007f00f7007f00000000b00b00b00b000000000000000000000000000000007007000777777000000000
8888888800007776677577700000777676777d6000f7007f0077777700000000b00bbbb00b0b00b00000000000000000000000000777777007c77c7700229000
888888880000777776777d600000777776777d6000777777007b777b00000000b00b8b8b0b0bbbb000000000000000000000000007c77c7777c77c770027a000
8888888800077777777677000007777777767700ff7b777b0077797700f7007fb00bb1b0b00b8b8b000b00b0000000000000000077c77c7777755777002a9000
8888888800077766d762d70000077766d762d700f7977977ff97787f00777777bbbbb700bbbbb1b00bbbbbb00000000000000000777557770777777000000000
888888880006d0dd066066000006d0dd06606600f77f7777f77f77f0ff7b777b0bbb77000bbb77000bbb8b8b0000000000000000077777700777777000000000
888888880006002000606000000600200060600007790f7007779790f79779770b0707000b0730b07b0bb1b00000000000000000797272707972727000000000
bbbbbbbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
bbbbbbbb600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
bbbbbbbb67700000000000000000000000000000600000000000000000700000000000000070000000000000000000000000000060000000000000000110ee00
bbbbbbbb67700000000000006000000000000000670000000000000007760000000000000776000000070d006000000000070d00d77000000000000001128e00
bbbbbbbbd77700000070d000d770000000000000d770000000000000d776000000070d00d77600000067dd00d77000000067dd00d77700000000000001188800
bbbbbbbbd7770000067dd000d777000000000000d777000000000000d77700000067dd00d777000000d77700d777000000d77700277770000000000000128000
bbbbbbbb277770000d7770002777700000070d002777700000070d002777700000d77700277770000677717027777000067771702677700000070d0000010000
bbbbbbbb2677700067771700267770000067dd00267770000067dd00267770000677717026777000067777752677700006777775006700000067dd0000000000
0000000000670000677777500067000000d777000067000000d777000067000006777775006700002267777700670000726777770006d76d00d7770000000000
000000000006d76d267777700006d76d067771700006d76d067771700006d76d226777770006d76d66d677000006d76777767700000077760677717000000000
000000000000777662677000000077762677777500007776267777750007777666d677000007777676677000000077777762d000000777772677777500080000
00000000000077777667700000077777726777770006777772677777000777777667700000077777777d670000077777777700000007777772677777001e8000
0000000000077777777670000007777777767700000677767776770000077767777d670000077767d7726600000777777dd770000007776677767700001e8000
0000000000077766d762d00007777766d762d00000006776d6660000000776ddd7726600000776dd00d7700007777766d002d0000007dd00d762d00000128000
000000000006d0dd066060000706d000d6770000000006777d0000000000770077dd000000007700000007000706d00000000000000070d0d677000000010000
0000000000060020006060000006000000d7700000000dd6d00000000000077d000000000000077d0000000000060000000000000000000000d7700000000000
cccccccc44444444000bbbbbbbbbbbbb444455334444454544544555bbbbbbbb000000000000122255440000000000077600000cd6666777d2d22d22dddddddd
cccccccc4444444400b3333333333533544454435454444445544454333333330000000000001224444400007600067cc7cc00c72d66667722222222dddddddd
cccccccc444444440b3345555544545445544445464455444544444453344535000000000000112444440000c7cc77cdc777c77c22dddd67222222d2dddddddd
cccccccc44444444054665554444544444544453544544464444444455445444000000000000122454440000cc777cddcddc7ccd22dddd66d2222ddddddddddd
cccccccc44444444b55651544444444445445445444445454454444444444444000000000000112554440000cddc1dd11cd11dcd22dddd66d2d22ddddddddddd
cccccccc44444444355555544444444444444545445444444445445444554444000000000000112255440000dd1111111111111c221111d6ddd2dddddddddddd
cccccccc44444444344511444544454454445445444544945444444444555444000000000005112445545000c11111111111111d2111111ddddddddddddddddd
cccccccc444444443554545544444444444444434544444444454444454444540000000055111242545544551111dcd11111111111111111dddddddddddddddd
4ffff7774444544454444454bbbbbbbbbbbbb0004544444533554544b0000000000000000000124454440000111111dd111c111176776767d2d22d2200000000
24ffff7744456554654445443333333333333b0044444456344544453b00000000000000000014244444000011dd111111ccd11156567565222dd22200000000
224444f7446656545544444413444354055433b0444444505444454445b00000000000000000114444440000111111111dc111111555555122ddd2d200000000
224444ff456655144445504444454444550664004405444435444554443b000000000000000014445444000011d111dd1111111111111111dddddddd00000000
224444ff4555500444555144445554444015655b44055444544544444443b00000000000000011244444000011dd11111111ddd121211121dddddddd00000000
2211114f40515044444101444055514440555053441164445454445444443b00000000000000114444440000111dd1111111d11112212111dddddddd00000000
21111114441014465440544441150044401104434440044554554545444443b000000000000011244544000011111111111d111122122222dddddddd00000000
111111114444444555044444444054455545455344444445344544444444443b000000000000124444450000111111111111111122d222d2dddddddd00000000
33333333333333b34ff44f4f4ff44f4ff4f44ff44ff44f4f8222100000000018000000000024400045ff4fff1111111111111d26d22d2dd212d1111100000000
3b33bb333333333322232322232252222205223223225022220201100000202200000000002220004212444211111111212d6d1dd1dd666dd1d2d21200007000
33355b3333bb43b33b10311101b3313113003b1001b30031150102110120105300000000002240000111111011111111d22d6dd660d666762dd2d22d00077000
3355bb3533b5553304b00b000030b0403000030000300003021200011000002000000000002440000011200011111111d1dd7666700666756666dd1d00076700
335bbb4333bbb54305b03b30b3b0bb500b000000000000b025010000000003520000000000242000001220001111111100dd66760000767067666d0000767700
335bb533335bb5530b030003b00000b00000000000000000040553000000004000000000002240000022400011111111000dd770000007000777600000777770
33333333333b5b333003003000000b5300000000000000000020020000000030000000000022400000244000111111110000d700000000000777000006d67dd0
33b353b333333333000030000000bb3000000000000000000022050000000200000000000024200000242000111111110000070000000000007000000dd766d0
00003333333300003353333333335353353333330000000000c0000000333300000000004ff44f4f45ff4fff000000000000000000000000776776700dd6d52d
003333b33b3333003433533bb33533333333333b009707000c9c0b00033b333000000000222422224212444200000000000000000007000055656756dd66dd5d
033333533533333033a555333353533333b533330073000000c300c0333333b3000000000111111001111111000000000000070007777000215555572d66dd15
035b33333333b5303baaa5333353333333bb333300003790000b3c9c3333333300000000000000000000114400000000000076706766670011111116d2262215
3533b333333b33533ba9aa3333333330033333330097307000c030c03b33333300000000000000000000144400000000000666756666dd761212111625222511
3b335533335533b333aaa5533333333003333353000733000c9cb300333b33330012570000000000000011240000000000d666761dd2d22d1122121661151211
3b33333bb33333b3b33a45b333333300003333b30000370000c030b0033333300125675000000000000011440000000001dd666dd1d2d212222122262d115121
35533333333335533333333bb33300000000333300303000000030000000400001256650000000000000112400000000022d2dd212121111222d222d22211111
00000000ffffffffffffffff00000000000000000000888080000000000000000000000000000000000088808000000000000000000000000000000000000000
00000000ffffffffffffffff00000000000000000088822888822000000000000000000000800000008882288882000000000000000000000000000000000000
00000000ffffffff0fffffff00000000000200000008222282282000011100000000000000000000000821128228000000d2d000000000000000000000000000
20000002ffffffff0fffffff02000000020220000000299922882000000111000000000009a9888000001dd122880000022d0d00000000000000000000000000
20000022fffffff000ffffff00202020002222000aaa99aa9222200000001100000000000aa999000aaaddccd220000002d00000000000000000000000000000
22002222ffffff0000ffffff0222020202222020000a12b019000000000001100000000000aa9000000a12801d0000002dd00000000000000000000000000000
22022222fffff000000fffff22222022222222028088a101a90000000000011000000000000000008088c101cd0000002d000000000000000000000000000000
22222222ffff00000000ffff2222222222222220000aa9aaa9000000000001100888800000000000000a9cccc00000002d011000000000000000000000000000
eeeeeeeefffff00000000fff000000088000000000aa99a99a90000000001108888888000000000000aad1cdd0000000d1888810000000000000000000000000
eeeeeeeeffff00000000ffff000000888800000000008992aa99000000088888888888800000008000008dd2c000000d2ccccc81000000000000000000000000
eeeeeeeeffff000000000fff00000888888000000008822aaaa990000088888822222888000aa9800008822ccc00000dccd00cc1000000000000000000000000
eeeeeeeefff0000000000fff000008888880000000888299a4a499000088882229992888009a9880008882ddccc200dccd0000c1000000000000000000000000
eeeeeeeeff000000000000ff00008888888800000088229aaa4aa990088822999aa992880099880000882adaccccc21cd88800cd000000000000000000000000
eeeeeeeefff000000000000f00888888888888000000094a4aaaaa90aa222299aaaa998800080000000022adccc1cc182222808d000000000000000000000000
eeeeeeeeff00000000000fff0808888888888080000009a4aa4a4a994aa2299aa00aa9880000000000002dddccc1dcddd2c88000000000000000000000000000
eeeeeeeef00000000000000f80888888888888080000999aaaa4aaaaa4a299aa2202a9280000000000009d9d9c1ddccc11cc8000000000000000000000000000
88888888ffffffffffffffff000000000000000000009494a99aa9aaaaaa9aa12102aa0800000000000028ddc811dc1cc10cc800000000000000000000000000
888888880ffffffffffffff0000000000000000000009949a494aaa99944aa1121102a9800000000000002d8ccc1ddd1d000c800000000000000000000000000
8888888800f0ffffffff0f000000000000000000000099989a498aaaa9a4aa1112100a98000000000000002c8ccc11d10000c800000000000000000000000000
8888888800000ffffff00000000000000000000000000198899988aaaaa4a11112110a900000000000000002ddddd1100000c000000000000000000000000000
8888888800000ffffff00000000000000000000000000119889999889984aa1110010aa00000000000000000110011000000c000000000000000000000000000
88888888000000f00f00000000000000000000000000011988888919889aaa01100002a00000000000000000d200120000000000000000000000000000000000