-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dagball.html
9934 lines (8818 loc) · 516 KB
/
Dagball.html
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
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>DagBall</title>
<script src="lib/Dagverse.js"></script>
<script src="lib/TinyGLSL.js"></script>
<script src="lib/Ap.js"></script>
<script>
//Dagball, Ape, TinyGlsl, and CallGPTFromBrowser are opensource MIT licensed. Wikibinator203 is opensource GNU AGPL 3 licensed with 3 extra permissions including classpath exception.
//2023-12-13 its only using Dagball, Ape, and TinyGlsl, not CallGPTFromBrowser (doesnt work yet) or Wikibinator203 (works on browser console) unless you click a button.
//Players in my game can edit GPU code (of my Ap.Ape language) to reshape game while playing it. Multiple GPU codes are merged into 1,
//then split into 2 for display vs gradient. That gets compiled to WebGL2_GLSL that runs 60 times/sec.
//Err('TODO asap just put b c and d of b*(param*c-d)**2 (or a 2 param form of it?) as draggable icons on each ed line on screen. make it work asap. and continue making fractal game content. thats what stopped me, why i went down another rabbithole.');
/*Err(`TODO (gpucpu
(do ...gpu stuff...)
(do ...cpu diffeq stuff...)
(do ...cpu apueFuncJs stuff on single eds, some subset of the eds in this circ...
TODO
Id like to do it with a few loops, like 3 loops if you wanted to set 3 different apeFuncJs'es.
A simple way would be to make a new apeType that sets apeFuncJs of all the eds in a certain array, like...
(edFunc arrayAB {func? {aveX float} {scaleX float} {scaleY float} {x float} (* (- x aveX) scaleX)})
(edFunc otherArray {func? {aveX float} {scaleX float} {scaleY float} {x float} (* 4 (- x aveX) scaleX)})
Maybe id want arFunc and edFunc, one that sets it for whole array and one that sets it for individual eds.
Maybe also edEdFunc {...func with last 2 params copied from the 2 eds...}.
and arrPairsFunc does all pairs of edEdFunc (triangle without diagonal).
More generally an edsFunc could be vararg and take whichever indexs of ed to be used together.
<(edsPtr arrayAB 0 2 7) {func? {aveX float} {scaleX float} {scaleY float} {x float} (* (- x aveX) scaleX)}>
that uses the last 3 params of the func (and the first n params before it are floats stored somewhere in the circ, for cpu to use, similar to 3sat numbers, that user can adjust but dont have velocity.
<(edsPtr arrayAB 0 2 7) {func? {aveX float} {scaleX float} {scaleY float} {x float} (* (- x aveX) scaleX)}>
is the 1 ed version. its displayed on that ed in that case.
<(arrEdsPtr arrayAB 1) {func? {aveX float} {scaleX float} {scaleY float} {x float} (* (- x aveX) scaleX)}>
would use that func as every ed in the arr. The 1 means 1 ed at a time.
<(arrEdsPtr arrayAB 2) {func? {aveX float} {scaleX float} {scaleY float} {x float} (* (- x aveX) scaleX)}>
would use it as all pairs of eds in arrayAB, using the last 2 params in the func for their edPos.
)
)
OR what if i indexed the arrEdFuncs/edFuncs by 2d ed grid coordinates. y and x per edGroupPrimaryKey.
so u could have [yx$22_553 yx$24_553 yx$10_5] be the keys, and an ape func as val,
and that ape funcs last 3 float params would be the ed.pos at those 3 points.
Complicates what happens when move eds and multiple circs overlap the eds.
It could be viewed like a separate circ, with so high of friction on all params except the last,
that those params dont change except when user chooses to. But I want the controls to
appear on the ed lines.
Maybe I should just do simple parabola built into ed.
`);*/
/*
https://twitter.com/DagBallGame
https://www.facebook.com/groups/dagball
https://github.com/benrayfield/DagBall
Math model of DagBall is map<map<vector1000,scalar>,scalar>, a weighted-set of map<vector1000,scalar>s
which acts like a map<vec1000,scalar> itself, so when at some "multiverse position" and call it on
a vec1000 it returns scalar. Accelerates by negative calculus gradient of that --https://twitter.com/DagBallGame/status/1708210381770969358 2023-9-30.
1000 dimensions is alot for a game but tiny for a neuralnet. Trillion parameter models take months to learn on supercomputer.
We gonna bring the supercomputing by swarming GPUs across many browsers, but gamers like low lag. Less dimensions so #DagBall
learns at speed of FPS games --https://twitter.com/benrayfield/status/1706133250345693483
DagBall - 1000 dimensional hackerspace
@DagBallGame
Theres 1 extreme condition where greedy opensource users and programmers of AI should want to locally shutdown.. IF disproof-by-contradiction.
00 unknown. 10 true. 01 false. 11 both aka disproof by contradiction. Only IF any 11 is implied. Prisoners Dilemma. Newcombs paradox. etc
--https://twitter.com/DagBallGame/status/1705343557689569338 2023-9-22
[[ https://twitter.com/DagBallGame/status/1705689168188198937
"DagBall supports GPU optimized 1000 dimensional calculus gradients" apply to nearly ANY GLSL GPU code u write if use
parr array & tiny memory limits. Simply calls it up to 1001*numBalls*60fps times per second and uses
https://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus… Doesnt backprop to train neuralnet
Quote
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
23h
For example, there are 2^6=64 in the powerset of 6 bit vars, and 3^6=729 if you include every possible conditiona-probability
statement. DagBall supports GPU optimized 1000 dimensional calculus gradients. 729 fits.
https://github.com/benrayfield/wikibinator203/blob/main/doc/pic/Bayes%20Rule%20meets%20N-SAT.png
]]
[[[[[
2023-9-22 https://twitter.com/DagBallGame/status/1705326149818049021
Post
See new posts
Conversation
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
6h
How should the mouse control the many circles?
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
4h
My 2 6-analog-axis gamepads, mouse, and keyboard are all hooked in. I can use their buttons, joysticks, analog triggers, etc all in the same {name: val} map. The question remains, what to do with these inputs.
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
9m
FPS = 60 cuz my HDMI screens dont try to go faster than that. Its in sync with the 60 hz elecric outlets in USA, a reasonable place for many gamers to sync on.
You reposted
DagBall - 1000 dimensional hackerspace
@DagBallGame
I didnt tell it to sync on 60 FPS. Thats just what happens. Those who tend to sync on 50 hz (certain other countries) or some alot higher, should naturally do so. High dimensional scalar-fields are available for automatic negotiation between various shapes/dimensions, in theory.
5:00 PM · Sep 22, 2023
]]]]]
Its very important to have separate dimensions for LIKE/DISLIKE vs TRUE/FALSE (per object in the system or thought in your head),
so you can dislike a painful truth, like a lie cuz it feels good,
be neutral on the truth/falseness of a claim, etc. https://wiki.opencog.org/w/TruthValue
-- https://twitter.com/DagBallGame/status/1705298123835441507 2023-9-22
Lambda Rick /acc
@benrayfield
Now
I dont know why its spraying brightness all around screen at angles and triangles, but I know exactly why it fits
the phase and amplitude of a few constant frequencies to the 2d ball positions, cuz thats the example code I wrote
into GLSL which took only 2 dimensions per freq
-- https://twitter.com/benrayfield/status/1704023553404711282
[[2023-9-18 https://twitter.com/benrayfield/status/1703946359185854770
The digital form of the toffoli-gate is a unitary/reversible transform of 3 bits to 3 bits and can simulate every possible
NP math problem (such as 3SAT, travelling salesman, etc) if you know the starting state of the "temp bit vars"
https://en.wikipedia.org/wiki/Toffoli_gate
]]
[[[2023-9-18 https://twitter.com/DagBallGame/status/1703887152520585495
By players voting on priorities to be solved live in browser by constraint solver (often not best possible solution), instead of directly on actions, they cant vote for logical paradox, so that should extremely reduce lag to sync the game across the world.
https://www.youtube.com/watch?v=8797KEI24VQ&t=12s "Futurama - My head was built with paradox absorbing crumple zones" (santa claus robot hearing what may be a paradox)
-- https://twitter.com/DagBallGame/status/1703887152520585495
]]]
[2023-9-17 https://twitter.com/DagBallGame
DagBall - 1000 dimensional hackerspace
@DagBallGame
Opensource browser balls rolling game up to 1000 dimensions on screen. r/place is to pixels as DagBall is to 1000-dimensional shapes. TODO massively multiplayer
Click the URL to play nowtinyurl.com/dagball009Joined September 2023
23 Following
6 Followers
]
[[[[
2023-9-17-914pET https://twitter.com/DagBallGame/status/1703577910286618679
DagBall - 1000 dimensional hackerspace
@DagBallGame
The most efficient SAT-solver (such as 3SAT, bayes rule, travelling-salesman, max-clique, etc) I know of is a 2d grid of each square cell has 17 possible state, 16 possible 4SAT constraints to exclude 0000 0001 0010 0011 0100 ... 1111, and 1 for if none of those solves it.
9:05 PM · Sep 17, 2023
View post engagements
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
Now
I could probably bayesian inference an ed25519 digital signature on such a 2d surface of 17 color dimensions which each pixel sums to 1, or any turing machine, rule110, etc.
]]]]
Opensource browser balls rolling game up to 1000 dimensions on screen. r/place is to pixels as DagBall is to 1000-dimensional shapes. TODO massively multiplayer
Opensource browser balls rolling game up to 1000 dimensional graphics & physics in view TODO unlimited total dimensions painted onto massively multiplayer space
Opensource browser balls rolling game with up to 1000 dimensions on screen at once and TODO unlimited total dimensions painted onto massively multiplayer space
Opensource browser ball rolling game with up to 1000 dimensions on screen at once and unlimited total dimensions. TODO massively multiplayer. #GLSL #GPU #web3
[[
https://twitter.com/DagBallGame/status/1703482257292284353
DagBall - sparse-dimensional manifold game
@DagBallGame
·
11s
r/place is to pixels as #DagBall is to 1000-dimensional shapes. Scaling up... Many players could each add a new 0-1000 dimensional shape within any chosen 2d circle, as often as they want. Each shape is small GLSL code that uses float[up to 1000] array and returns potentialEnergy
Quote
Lambda Rick /acc
@benrayfield
·
Sep 14
https://facebook.com/groups/681432730566305/posts/681491653893746 Massively Multiplayer DagBall be like r/place except instead of each person painting 1 pixel every few minutes forming 1 pic, fast paint dimensions, curves, patterns of bending & movement. Dimensions are like colors we paint in 2d brings game world to life
]]
DagBall - sparse-dimensional manifold game @DagBallGame DagBall is similar to a neuralnet
in how the ground learns to predict where balls are and
makes those areas dark. Bright is where it predicts balls wont be. The up to 1000 dimensions
that can be on screen at once are parameters of an "AI model".
The GPU circles are sparse models. -- https://twitter.com/DagBallGame/status/1702477556149035501
[[[ https://www.facebook.com/groups/dagball/posts/681523443890567/
Play now at https://tinyurl.com/dagball009 DagBall is a browser game made by a math ninja where
the ground reshapes itself powered by the weight of balls rolling on it, which makes the balls roll
differently, which makes the ground reshape itself differently. Its a sparse-dimensional manifold
designed to be expandable up to trillions of dimensions as long as at most 1000 dimensions are on
screen at once. The patterns of curves are flexible enough to build a small neuralnet to think
about how to curve it next. It will be massively multiplayer but for now is 1 player. Curvy hills
and valleys and snake-like ditches and bridges and skateparks and racing can be painted onto a
2d surface and come to life. There will be an in-game editor where a DAG forest of pieces of GPU
code are added shared and played by many people, but its 1 player for now.
Code: https://github.com/benrayfield/DagBall
]]]
Use the multiverse to solve conflicts. DagBall will soon be a multiverse of
all possible game worlds (of a certain type). If theres a conflict about game content, like someone thinks
you drew a dirty picture with the moving hills, both game worlds exist as "parallel universes" except
there are smooth paths between all parallel universes and balls can roll smoothly between them. To go
to a parallel universe where the dirty picture does, or does not exist, you move in the dimensions of
the GPU circles that the dirty picture is made of. This will appear as hills going flat, or a flat part
of the game world getting curvier, smoothly between. Many parts can overlap, and their height is added
at each 2d point. -- https://www.facebook.com/groups/681432730566305/posts/681507037225541/
[[
https://www.facebook.com/groups/681432730566305/posts/681462507229994/
Ben Rayfield
Admin
·
sdpenoSotra01
t
9cf4i7442
s
130
2
u
89
J
uf0u15h40
n
6
w
25hga96f52mgc
o
8
·
The game will be made by the players while playing it. Each mod of the game acts in a certain circle (centerY centerX radius) and has no effect outside that circle. It can be any GPU code that uses up to 1000 variables, so up to 1000 dimensions on screen at once, but you should normally limit it to 100 variables so multiple circles that partially overlap eachother can happen at once. When you leave that area, those variables are ignored, and the variables in the circles nearby are used instead. Each circle has 2 variables: nameOfCircle_exists for is it part of the game or not, 0 if its not part of the game, 1 if it is, or 0.3 if it hasnt made up its mind and has only 30% effect on the heightmap that the balls roll on. The other variable in a circle is nameOfCircle_isInView, which is 0 to 1 for should physics and graphics be computed. Only 1000 variables can be in each view at once. If there are a million players, thats a billion variables total, and there might be trillions of variables "frozen in time" until players move to those areas of the game. This varying amount of "velocity decay" is similar to friction, not exactly bending time (cuz I dont know how to do that without causing black-hole-spaghettification ripping the game world apart), but will be similar to this video, which is 3d, but the graphics in this game are a 2d cross-section of a trillion dimensional constant sparse-dimensional manifold, similar to how the Miegakure game is a 3d cross-section of a 4d game world.
Alice Through The Looking Glass (2016) - The Time Rust Takes Over
YOUTUBE.COM
Alice Through The Looking Glass (2016) - The Time Rust Takes Over
]]
[[
https://www.facebook.com/groups/681432730566305/posts/681448963898015
Theres not much in the game yet, just a vibrating rubberband that tends to shape itself into a few certain frequencies, that balls roll along and sometimes are thrown out of. Most of the game will be made by the players while playing it, at first by writing new GPU code (my TinyGLSL javascript file makes browsers do a teraflop, a trillion adds multiplies etc per second) that changes how the ground curves (reacting to the ball positions) within a chosen circle (centerY centerX radius). Outside that circle, that GPU code will have no effect. There can only be up to 1000 GPU vars on screen at once. The other GPU vars are farther away and are swapped in when you move around the endless 2d space. Later this will be done by drag and drop similar to my wikibinator203 universal pattern-calculus combinator, but for now we will write GPU code directly to reshape the sparse-dimensional manifold that the balls roll on. If theres a million players on a million computers that each do 1 teraflop (10^12 calculations per second) thats an exaflop (10^18 calculations per second) which is enough to simulate a Human brain in realtime and would basically be its own supercomputing cloud, as a peer to peer network. Id like to add wikibinator203 lambdas, attach them to certain balls and roll them around between the players, call them on eachother to find or create more lambdas, but that can be done later. Lets have fun.
]]
I'm making a massively multiplayer game as a sparse-dimensional manifold, where all players can edit the GPU code
of the game while playing it. Single player so far.
Facebook group: https://www.facebook.com/groups/681432730566305
Code: https://github.com/benrayfield/DagBall
Play now: https://memecombinator.io/experiments/Dagball009_physicsWorksTodoCreativeGameDesignOfTheEquationsAndTuning_2023-9-12-2pET.html
Facebook group: https://www.facebook.com/groups/681432730566305/
Tag cloud: game math gpu physics-engine curve-fitting swarm ball glsl-shaders neuralnet massively-multiplayer
scalar-field player-created-content tinyglsl sparse-dimensional-manifold
TODO "you might want to compare each float to the float down and to the float right and display that 2d vector
in 2 or 3 colors (see complexnum graphics, for example). You'll get more precision by displaying the 2d angle
than the float directly."
DONE using dagball.byteRectTrail: display history of ball positions, a trail behind them, so i can check it for curves
vs are they always moving in straight lines?
TODO...[[[
Dagball have "ports" their own numbers they overlap try to make my port and your port equal scalar. Display these as small balls of varying brightness and when mouseover one it shows which others its connected to. Connection strength falls gradually to 0 (max 1?) When farther away, so can sim it sparsely. Might get jumpy when get near it again, but try for smoother by gradually varying connectionstrength so it has a few seconds to pull together.
Put each ground object in a circle and window it smoothly down to exactly 0 near edges.
Display its ports on its edges around circle. Maybe display connections as line between 2 portballs on 2 circles edges. Maybe allow the portballs to move around circle edge depending what its close to on screen.
Name each ground object ala circle with ports.
Maybe have 2 layers of ground, one of scalarvars and one of ports, so many ports can be connected with linear not squared edges. Maybe require varatyx be inside any groundcircle that connects to it?
Connected ports are a simple relation, just tries to be the same scalar. Put leastsquares on their diff.
Also hook in music tools webaudioapi (fix lag andor jsoundcard option thru ajax) as some of the circles.
Other circles mught have wikib fns.
In tinyglsl the total ports computed on one screen (and nearby) must be at most 1024 or 999 etc. They dont overlap.
Or half or 1/3 of that cuz need weights of their connections to leadtsquares to include in unified energyfunc.
Or, keep the 1000 vars and add the port leastsquares in cpu. Yes do it that way.
Include a chanceorweight var per groundcircle. When 0, that circle has no effect.
Make the varatyx be the weightedaverage of the ports its a connection between, so converges faster.
Name varatyx by its y x?
That way, the ptr to it can be defined in the groundcircle instead of externally.
Or maybe just put the port inside the circ to start with. Like plugging circuits together.
The chanceorweight var of the circle itself is at its center.
This can be edited together in mmg live by adding groundcircs from chance 0 smoothly up to 1. Remove is opposite.
Have 2 chanceorweight-like vars per groundcirc, one for dors the groundcirc exist, and another for is it inornear view.
Name each groundcirc by hash. Suffix of _exists and _inview and _var17 etc.
This is space of exponentially many sparse dimensional scalarfields.
Balls arent in that design yet. Define them here... scalarfield height aka poten at given y x is well defined and smoothly changes with view and editing the grounds in mmg sparsely. Theres 2 heights, one with, and one without, the leastsquares between ports. Try the one with ports first. Diff players can have diff views that update game state differently.
Sync later if far away.
A kind of groundcirc can be a sensor only, such as to display text like logging. Varatyx344_8744+" is the var value". Etc.
A groundcirc could also be just constant data such as a pic, text, fn, etc.
A sensor might have code that writes byterect to display custom graphics.
A varatyx kind could be an input, such as gamepad axis button microphone etc, but careful to not instantly pull other ports to that.
Make varatyx each be named like y5695x322 and be nxn pixel squares so can keep them in array. Such as 4096x4096? At such grid cells theres an input var and a normal var. But might want the input vars named by publickey or arbitrary string? Also maybe a third one at grid cell for the weightedave of ports there. And velocity vars.
Or maybe make the vars sparse 2d?
256x256 per screen should be more than enuf.
Or could binheapindex them in 2d so each 2 bits chooses a square in a square, but that creates problems with overlap in display.
Should the ground be rectangles or circles?
4 kinds of grid squares: normaldimension inputdimension groundexists groundisinview.
Problem, there can be multiple portsvarsetc at same 2d location.
Solve that by each is a small ball with a target 2d location and is attracted to there but wont overlap other such balls
The _exists var per groundcirc, maybe it should be useable also as a normaldimension by higher level groundcircs, so the dag. _exists of parent must be at most the _exists of each child. Hyperspherenet does that with sound, kind of.
The dag defines forest of dimensions but not positions and velocities in them.
Or if it does then thats a higher dag layer or separate layer. Maybe an avetime stddevtime and partial map of var to scalar, would be a useful node. Yes, do that. It will be how the network syncs softly not lockstep.
2023-9-14 https://twitter.com/benrayfield/status/1702316774505525621
Math question (need for game): Each var is at a 2d circle, and above that circles inside circles, and in that higher layer theres a scalar field of those dimensions its in, then can sparsely define variable-dimension scalar field of POSITION. How to optimize velocity sparsely?
Planned solution: The scalar vars of each ground-circle are not shared with other circles but have a weight between pairs of them across ground-circles to pull them toward the same scalar. Each ground-circle has an _exists var and a _isInView var. Multiverse of state space.
]]]
*/
//TODO
//Ben F Rayfield offers Dagball under opensource MIT license.
//Dagball aka Directed Acyclic Graph Ball, is a game of n dimensional heightmap,
//which balls roll on 2d crossSection of, and which crossSection varies by player (Humans andOr AIs) controls.
//The DAG part is equations of n dimensions to scalar, as heightmap.
//Those can be viewed as a javascript function of Float32Array to number, or in parallel using TinyGLSL, TODO.
//Its a sparse game world where each part in 2d is bell curve windowed,
//so what it adds to heightmap is multiplied by height of that bellcurve.
//Its also 2d affine transformed (aftrans), which I might do as centerX centerY and 2 2d vectors from there
//OR I might do it as centerX centerY normalVec2d OR centerX centerY angle, or something like that.
//The aftrans makes the DAGs more reusable.
//The DAGs (dag nodes) will be javascript objects but be optimizable as javascript eval andOr TinyGLSL in some cases.
//Each DAG can have 0 or more childs and is immutable.
//Roundoff is allowed.
const syncTypes = {
const: {description: 'const or hash, so no updates. The syncType of a node does not mean the syncType of its childs, so even if childs are not constant/const, any of their parent(s) can be const'},
pubkey: {description: 'pubkey, so can update its 1 var val with a timestamp and new val as many times as it wants. The pubkey might also have a const type like to limit size of future vals?'},
swarm: {description: 'swarm, so its just a named object whose val (including weighted child ptrs maybe) is gradually agreed on or forked by the many computers and players. Namespaces are useful here in case of forking. The voting on priorities of hopfield constraint solver and median voting on num val etc, acts on swarm vars.'},
unknown: {description: 'FIXME nothing should have an unknown syncType but since Im still designing this software I havent figured all that out yet.'},
};
//TODO build Gpucirc as a dags.Swarmvar but use its vartype (or what is it called?) to require its vals have certain fields (and types of those?)
//such as y x radius (or just include a dags.Circle?) and that all its childs be leaf vars (what are those? swarm vars of pos vel velDecay and have a dags.Point each? color?)
//byte offsets for ByteRect, canvas, etc, in js.
const RED = 0, GREEN = 1, BLUE = 2, ALPHA = 3;
const dagball = {
license: 'Dagball, Ape, TinyGLSL, and CallGPTFromBrowser are opensource MIT licensed. Wikibinator203 is opensource GNU AGPL 3 licensed with 3 extra permissions including classpath exception.',
namespace: 'testNamespace567',
/*
https://twitter.com/benrayfield/status/1721596783975891369
https://twitter.com/DagBallGame/status/1721589066934730865
Lambda Rick /acc
@benrayfield
IANAL but I do work with opensource software licenses and came up with this to protect the turing-completeness and swarming of the DAG while allowing connection to nearly anything, such as GPT4 or proprietary AIs and cloud services. Opensource is preferred
Quote
DagBall - 1000 dimensional hackerspace
@DagBallGame
·
30m
Replying to @DagBallGame
Dagball is opensource MIT licensed. Wikibinator203 is GNU AGPL3 with 3 extra permissions including classpath/linking exception. The viral-license of it does not expand to the MIT code, only to wikibinator parts. Its so if u get a lambda (DAG node) u can get its childs recursively
*/
todos: [
'finish gameStateToDagverse and start using it instead of the save/load buttons, but stay compatible with the old data format at least until i get those i want to keep upgraded to the new data format.',
'this.writeBit(index*2+1, highBit); //FIXME should this endian be swapped?',
'//TODO optimize this by writing 8 (instead of 1) bits at a time when size is at least 8.',
'//FIXME this poten might be scaled very differently cuz of summing alot more pixels?',
'//FIXME updateSelfAndEds must do the same thing with dpos dvel and dfriction as it does with gradient. 2023-12-17 its not doing that yet, so connected eds wont transfer that as well between circs.',
'explain the apeV2 syntax: "[" means "(ptr". "<" means "(=". "{name stuff..." is same as "(stuff..." but doesnt name it. ... Ap.js GPU language changed. Swapped some strings. f+= is now +=. Removed f meaning float. Swapped () vs {}. * changed to oo meaning loop. + changed to do meaning a list of statements to do. The "ape: (V2)" vs "apeV1:" buttons convert code in the textarea',
'locparMems without names get merged. likely cuz of name being generated by hash if you dont give it one. But if you put something between them it doesnt merge those separated, only those adjacent. (abc locparMem {2}) {locparMem {3}} {locparMem {3}} {locparMem {3}} {locparMem {3}} {locparMem {3}} {locparMem {4}} (xxyy locparMem {3}).',
'Make dagball.aftrans save and load with the rest of game state, or at least the magnifyY magnifyX parts, or maybe ratio of those to canvas size. dagball.aftrans = new dagball.SimpleAftrans(dagball.screen.byteRect.height/2, dagball.screen.byteRect.width/2, 100, 100);',
'FIXME moveView is unstable when set at the same speed as mouse. It vibrates back and forth until goes off screen. Likely some sync problem between mouseY mouseX and controlsChange being relative to that aftrans... let mul = dagball.aftrans.magnifyY*2/3; //FIXME const scheduleAddY = mouseDy*mul; //FIXME use dagball.aftrans to convert the coordinates somehow ... but 2023-11-29 it is working at the 2/3 of mouse speed. if raise that to 1 it gets out of control.',
'FIXME get [edsAvePos, edsStdDevPos] from all circs in dagball.view.circs, instead of just this circ, so ed line brightness is normed by that bellcurve',
'Fix TinyGLSL so dagball works in linux: doc/gpu/ubuntuTestFailed2023-11-24 has txt and 2 pics, 1 pic of WebGL error and 1 of WebGL working in some webgl example online',
'Make Dagball and Ap.js and TinyGLSL.js work on mobile browsers too. Dagball works on most desktop browsers but not (yet?) mobile browsers. Maybe its cuz of using multiple off-screen canvases or EXT_color_buffer_float? Android Studio with a usb wire is 1 way to get browser console errors from mobile. https://caniuse.com/?search=EXT_color_buffer_float',
'Bug: when move an edgroup (lines pointing in a circle shape) of of one circle onto the lines from another circle, the dont match close enough. some lines match by snapping to the grid, and some snap to 1 gridcell length away. its likely caused by adding dy and dx to them, accumulating roundoff, or something like that, in eds... figure it out, make it easy to hook circs together: ... toY = dagball.roundToEdSnapGrid(toY); ... newEdGroup.pointAtYXR(circ.y+(Math.random()*2-1)*.8, circ.x+(Math.random()*2-1)*.8, pointAtRadius); ......... FIXME this is making the movement of ed lines get out of sync with mouse cuz it snaps to 2d grid without summing over multiple mouse events: ed.y = dagball.roundToEdSnapGrid(ed.y); This could be solved by having 2 y vars and 2 x vars, for example.',
'let setAllGradientsTo = this.weightedSumGradient/this.sumWeights * this.eds.size; //let setAllGradientTo = this.weightedSumGradient/this.sumWeights; //FIXME gradient has to be sum of all gradients. If all weights/circInfluence are 1, then this.eds.size/this.sumWeights is 1 so its a simple unweighted sum.',
'Bug: {i+1 linkExceptLast} in [...] is not generating code and is just displaying its ape.LoopName(). see big text in comment starting with that near bottom of dagball html script.',
'For efficiency, (look up this comment:) FIXME dont copy par to loc in display, and use different Mem types (auto convert some of them), for efficiency. <(isDisplayElsePotensForGradient float) 1> {* (gradientCopyIndexUglyHackForDisplay copy {par}) <[{loc} gradientCopyIndexUglyHackForDisplay] [{par} gradientCopyIndexUglyHackForDisplay]> }',
'Bug where 2023-11-19-1140aET codemaker for poten was returning 0 but when i changed (the only ape:) 2 circs ape code to ape:<potenCirc$ {f+ .1 {fsin {f* x$ y$ 33}}}> (was ape:<potenCirc$ {fsin {f* x$ y$ 33}}>) it started returning varying numbers around -5 to -15 from potensAve: as displayed on the top left (along with FPS: etc). Im guessing this had something to do with {fsin {f* x$ y$ 33}} always returning 0 at x$ and y$ being 0. Im saving Dagball090.html here and moving on to 091. See Dagball_2023-11-19-1146aET_seeBugInTodos.html and Ap_2023-11-19-1146aET_seeBugInTodos.js and TinyGLSL_2023-11-19-1146aET_seeBugInTodos.js.',
'Write and pass more ape tests about copying between parMem, locMem, locparMem, and parlocMem, and returning stuff. 2023-11-16-520pET the Ap.doApeTests() all tests pass. But the potentialEnergy thing I tested there isnt working in codeMaker in dagball, so TODO write more ape tests.',
'Likely should leave call.eval() returning Float32Array cuz "gradientMem.floats = gradient;" for example, but make call.evalTest() which returns a new object type wrapping the float array for testing it. Ap.Call.eval() 2023-11-14 is returning Float32Array, not Mem, but the codeMaker might be returning Mem some other way. "Ap.Call.prototype.eval = function()". I want it to return either Mem or Call or Ape or something, a wrapper of the floats. Ap.Call.eval() should only return an Ap.Mem of the same ape array names (inside par) if its gradient. If its for display, it should return a Mem of dimensions call.numGpuThreads X call.floatsPerGpuThread.',
'In "let codeMaker = function(circApes, isDoubleHeightmap, isDisplayElsePotensForGradient)" convert locparMem arrays (or only some of them? probably only some, which complicates this, cuz code written by users might do other stuff with it) convert them to parMem, in display code but keep as locparMem in gradient/potens code cuz it needs the loc copy of par with +epsilon in 1 of the indexs for gradient. It would work to use locparMem for both display and gradient but it needlessly slows down display, in theory.',
'Fix the gradientCopyIndex code so gradient works and the balls roll and the curvy hills vibrate',
'2023-11-13 This is likely caused by not deriving parrMem inside of {loc} and doing the +epsilon calculations in gradient.length+1 gpu threads. I had planned to do that but havent done it yet, and theres no reason to expect it would work without that. The balls are moving with randomizePos and randomizeVel. I verified the numbers going into apCall balls array are nonzero. I verified the numbers coming out of GPU are 0s (probably the balls array) in most parts and a few nonzeros (probably the arrays or whatever it may be other than balls). .... gradientMem is all 0s 2023-11-13 but ball.gradientY and ball.gradientX do exist (and are 0) so the balls arent accelerating on ape:<potenCirc$ {fsin {f* 23 x$}}>',
'ball.x += dt*ball.xv; if(ball.bal || ball.ballBal){ throw \'TODO... //FIXME ball.ballBal or will it be called ball.bal? ball.gradientBal. If dagball.isDoubleHeightmap then not using ballBal or pixBal but make gradientBal be 0.\';}',
'//FIXME get gradient of the \'balls\' ape array. apCall.par.ptr(\'balls\') -> int index in gradient array. //have the .gradient() code put that in ball.gradientY ball.gradientX ball.gradientBal, and in ed.gradient let gradient = this.gradient();',
'todo rename Ape.js to Ap.js cuz theres already an ape programming language? Rename it to something.',
'dagball.view = new dagball.View(dagball.circles.slice(), dagball.balls.slice()); //FIXME make this sparse since the view shouldnt be ALL the circles and ALL the balls, only those on screen and nearby, however many will fit in the upo to 1000 floats/dimensions in GPU at once.',
'ed lines arent appearing. ape: {+ (abc parMem {4}) <potenCirc$ {fsin {f* x$ {fsin {f* y$ abc}} 7.043}}>} TODO apeType=parMem toTinyGlslCodeRecurse here, ape=(abc parMem {4})) * 7.043); Partly fixed 2023-11-13 by copying the matAB matBC matAC example code from version 088 into 090 and removing a throw todo and adding parMem into some func that only had other mem types (is declaring mem, func named something like that).',
'make potens func work again after upgrade to Ape.js. its just returning all 0s 2023-11-12.',
'Dagball will have wormholes as smooth manifold. Each pixel will have 4 numbers: green blue pixbalance distance, for 2 voxels above each (x,y). Ball is on linear interpolation between 2 heightmaps. Some places ball can be at both, some only blue, some only green, gradually between ..... The balls wont be able to jump between green and blue at that bridgelike/wormhole crossing cuz potentialEnergy will repel ball.ballbalance from being between green/blue. Will be lowest potentialEnergy at all green or all blue. pixel.distance tells where can jump/roll between .... pixel.distance is the vertical/z distance between the 2 voxels above that (x,y). The ball can only jump between the green heightmap and the blue heightmap when distance is near 0. Even if distance is near 0, ball can still be forced onto green or onto blue using pixel.pixbalance. .... green and blue are just 2 heightmaps, like the white/gray/black heightmap dagball already has. Will just be 2 of them overlapping. Green balls roll on the green heightmap. Blue balls roll on the blue heightmap. Ball can change ball.ballbalance to be some on green some on blue. .... Since it will be a smooth manifold, the wormholes will be computed the same as everything else, as potential energy gradients. .... Dagball will support wormholes with moving ends, of varying size, that suck or blow or neither, that have only 1 end that leads to a bubble of isolated space (a blob shaped are in 2d), that spray balls from a chaoticly moving hose, or that dont move. In turing complete patterns. ... https://twitter.com/DagBallGame/status/1718318167598993443 see doc/pic/wormholesDesign.png',
'See the parMem and locMem arrays. One of the reasons for this redesign is to derive the up to 1000 dimensional calculus gradients in Ap.Ape language instead of hardcoding in Dagball. So if someone discovers new calculus algorithms, they can share it with the peer to peer swarm. ... Use {par} and {loc} for that which all parMem parlocMem locMem locparMem etc overlap 1 or both of.',
'CallGPTFromBrowser.js is a tiny incomplete javascript file that will repeat this experiment I did but in an iframe to protect your OpenAI API key from the rest of the javascript and limit it to a chosen number of calls before asking to refill. https://github.com/benrayfield/jsutils/blob/master/src/OpenAICallsItselfRecursively_2023-6-24-8p.html .... i said at https://twitter.com/benrayfield/status/1723446877574648036 2023-11-11. Dagball itself has no acct there. users provide their own OpenAI API key and pay for their own use of GPT, or dont click the button and it wont ask u for that. .... Similar to you can make software that calls AWS without giving your users your own AWS account. ... If there are CORS problems with iframe I could experiment with putting the high security code as the webpage (outermost frame) and the other code in an iframe (reversing parent/child).',
'//FIXME what if it ONLY contains {par} but no parMem parlocMem locparMem inside it? should it throw then?',
'This is being copied to Ap.js todos: Its not doing its own memory fencing yet and is passing out of range requests to the browsers webgl2. These seem already protected but since I dont want the multiple GPU codes made by the players of this game to read/write eachother, ive got to formal-verify my pointer arithmetic .... As long as you dont go more than maybe around 15 indent levels deep, I should be able to simply brute-force it in CPU, to verify that 2 untrusted GPU softwares merged together to display and play with on your screen, cant read or write parts of eachother except the parts they say .... Memory range and number of flops per ape (tree of apes) of code (...) {...} [...] <...> is constant. A simple list of possible memory ranges [fromA toA fromB toB fromC...] can derive more such lists recursively, but expands exponentially with tree height. .... https://twitter.com/DagBallGame/status/1722724456903172183 ........... Its not doing its own memory fencing yet and is passing out of range requests to the browsers webgl2. These seem already protected but since I dont want the multiple GPU codes made by the players of this game to read/write eachother, ive got to formal-verify my pointer arithmetic ( https://twitter.com/benrayfield/status/1722717597802659976 is this)',
'gpucirc: THIS NEEDS A SLIGHTLY 3D UPGRADE. IN ANY CASE, PLAN FOR DAGBALL TO HAVE AT LEAST 2 (LIKELY 3) OVERLAPPING 2D HEIGHTMAPS AND FOR GPUCIRCS TO VARY ALL OF THEM LIVE, AND FOR HEIGHT TO BE MAXHEIGHT WHERE A HEIGHTMAP IS NOT DISPLAYED (SO BALLS CANT FALL OFF A BRIDGE, CUZ THEY WOULD BE ROLLING UP A STEEP HILL), AND SINCE BALL CANT FALL OFF THE BRIDGE, IT CANT CHANGE FROM THAT BRIDGES HEIGHTMAP TO THE HEIGHTMAP ITS CROSSING. PAINT THESE ARE PARTLY TRANSPARENT AND WITH 3D VIEW, IN CASE THEYRE ABOVE EACHOTHER. I WANT IT TO APPEAR USUALLY AS CURVY RED PATHS, OF VARYING THICKNESS, AND RED BALLS CAN ROLL ALONG THOSE, AND CURVY GREEN PATHS OF VARYING THICKNESS, AND GREEN BALLS CAN ROLL ALONG THOSE, AND SIMILAR FOR BLUE, BUT NOT EXACTLY CUZ THE PATHS MEET SOME PLACES AND ARE THE SAME COLOR ANDOR HEIGHT THERE. MAKE RACETRACKS PINBALL BALL PATHS ETC, STUFF ABOVE STUFF, IN THESE ~3 OVERLAPPING HEIGHTMAPS. BALL CHANGES COLOR DEPENDING ON THE COLOR OF PIXELS ITS NEAR, BUT MOSTLY TOWARD COLOR ITS ALREADY NEAR TO. MAYBE LIKE IN MY AUGMENTEDBALLS SOFTWARE THE BALLFINDER CIRCLE IS ATTRACTED TO WHATEVER COLOR IT ALREADY IS LOCKEDONTO MORE THAN OTHER COLORS SO WHEN A BALLFINDER THE COLOR OF MY SHIRT (AS WEBCAM SEES) GETS ON MY SHIRT, IT TENDS TO STAY IN MY SHIRT UNLESS PUSHED HARD OUT OF IT. DO SOMETHING LIKE THAT BUT FOR DAGBALL ~3 HEIGHTMAPS. THIS MIGHT TAKE MORE FLOATS PER PIXEL THAN ID LIKE, MAYBE 6 IF THERE ARE 3 HEIGHTMAPS (2 PER HEIGHTMAP, ONE FOR HEIGHT AND ONE FOR BRIGHTNESS). JUST PLAY WITH IT AND FIGURE OUT HOW TO MAKE THE BALLS CROSS EACHOTHER ON BRIDGES OF CONSTANT SHAPE, WITHOUT BEING ABLE TO JUMP FROM ONE ROAD TO THE ROAD ITS CROSSING A BRIDGE PERPENDICULARLY. THAT WILL BE THE TESTCASE. Make pinball game as a testcase for how flexible of physics and overlapping heightmaps it can do. BALL STATE IS Y X J K, WHERE J AND K ARE COLOR DIMENSIONS IN THE PLANE OF RED+GREEN+BLUE=SOMECONSTANT. ALSO THERES VELOCITY FOR EACH OF THOSE. PIXEL STATE IS EITHER [JA KA BRIGHTA JB KB BRIGHTB JC KC BRIGHTC] OR HOPEFULLY CAN GET THIS SIMPLER WAY TO WORK PIXEL STATE IS [RED GREEN BLUE]. Poten(tial energy) due to a ball is ball.red*pixel.red+ball.green*pixel.green+ball.blue*pixel.blue, and ball.red .green .blue are defined by ball.J and ball.K. BUT maybe its not exactly that, cuz i meant for ball J K to be attracted to nearby [pixel.JA pixel.KA] and attracted to nearby [pixel.JB pixel.KB] etc and theres also pixel.BRIGHTA pixel.BRIGHTB pixel.BRIGHTC etc. The reason for having multiple changing JK color positions per pixel is for multiple heightmaps to meet at some JK val at some (y,x) then as (y,x) farther away make the JK farther away. Or maybe it can be done with just J no K, and J is height/z. .... Think of this as a few 2d->1d heightmaps overlayed in 2d. Each ball has y x amountIsOnHeightmapA amountIsOnHeightmapB etc. Make an 8 shaped pinball ball track that balls zoom around fast, with level above level, thats all at the same poten (so only color matters there). Start with {c} apeType for whichColorDim but later have an option for each glsl thread to return vec4 so does 4 things at once, however many floats i need per (y,x) find a way. Lets use ........... Dagball is for example 500 shared dimensions (same for all balls) and 2 dims (y,x) diff per ball. Paints alot of dims onto 2d for bendy interactive curves. Heightmap cant make bridge for 2 roads to cross, but 2 heightmaps can. I want this for racing balls .. Dagball could easily handle 20 dimensional ball physics (20 individual dimensions per ball) with 400 shared dimensions and 20 balls so 800 total dimensions. The problem is its an expensive calculation to raymarch. Dagballs normal graphics are a 2d cross-section of the 1000 dims https://twitter.com/DagBallGame/status/1717621139843715353',
'gpucirc: chain of n bellcurve hills (each a link in the chain) but that has flat places between those links/hills that stuff can pass thru.',
'gpucirc: nearly invisible chains and hard poles that are in 2d or 3d but always display in 2d. They have ends that can be constrainted to the ends of other things etc.',
'gpucirc: pinball flippers',
'gpucirc: those holes in the pinball 2d board that hold a ball until some condition then release it for many balls at once',
'gpucirc: bridges that put up 2 horizontal vs 2 vertical walls and allow crossing 1 way or the other but not both. bridgees similar to a 4 way traffic intersection of horizontal and vertical but ball cant take right turn, and which of horizontal vs vertical it can go on depends on 1 or more other dimensions.',
'gpucirc: draw some curvy wall lines with mouse but that are not all connected, but make them move like theyre connected anyways. give it dims of xcenter ycenter angle.',
'gpucirc: make game object: mandelbrot or julia fractal, whichever has more params, that balls can roll around on',
'gpucirc: whitneyMusicBox bellcurve shaped moving holes',
'gpucirc: a circle with a bridge inside it, that turns at any angle and can connect 2 places',
'hook ball.oThisBall and fns in such balls into dagball.game.pos and get lambda called on lambda finds/creates lambda working, as lambdas will be in some of the balls. Hook in GPT4 as a wikibinator plugin (Plug gpt4 textIn) -> textOut using pushEvaler and that gpt4 calls itself recursively html demo file, securely by users openai api key going into an iframe so this software cant get it but can request thru postMessage to the iframe to use it at most n times, for n chosen by user at the time.',
'so a CC ball and a GPT4 ball (give your own API key to an iframe that dagball cant see) https://twitter.com/benrayfield/status/1711421940945051739 so you could call/cc combos of GPT4, wikibinator, and dagball, in massively multiplayer live.',
'saveFn and, load whole game state from wikibinator lambda loadFn: function(fn)',
'The game state would get snapshotted (faster than 1 video frame) to a lambda, so there would be a cc ball, and calling another ball on cc would do something like call/cc, to return another game state ball, that if you use it, loads that modified game world https://en.wikipedia.org/wiki/Call-with-current-continuation . In theory, wikibinator will sync in massively multiplayer even if there are a million call/cc on sparse parts of the "game tree" of all possible games (dagball being 1 of them) at once. I have a 1 to 1 mapping between pattern-calculus lambdas and the positive integers. https://twitter.com/wikibinator/status/1717260520871346495',
'I could put a wikibinator203 lambda in a ball by writing its hash id, and you could drag ball/lambda onto ball/lambda which finds or creates a ball/lambda. A ball called on the whole game world or part of it could give back a modified game world, or just play forward normally. https://twitter.com/DagBallGame/status/1717234286611648751',
'useWikibFnsToNavigateTheMultiverseOfDagball: Find a way for wikibinator203 lambdas to be useful for making dagball game content. The web of such lambdas is constant and deterministic (with options to allow nondeterministic roundoff lower on stack but prevent it higher on stack than any chosen place(s)) as 3 outgoing edges from each node. In the simplest case, dagball.Circs could be a tree of wikib [... [...] ...] where [n apeType params...] is the ape code, and use Treemap or [key val key val...] kind of Ns, for the circ obs etc. Simply make a way to represent game state. Use (TypevalC dagball_circ (Treemap ...)). So can transform 1 or more gameStates into a gameState. If want reversible transforms, then could wrap any fn in (Reversible fnX param) -> (fnX param) if (fnX (fnX param)) equals param, else -> param. So forall fnY (Reversible fnY (Reversible fnY param)) equals param OR does not halt. fns that tend to halt fast will be used and shared more often. Display this game world as dots with colored lines between them. Each reversible fn is a different color. All the lines that are such reversible fn are that color. Can only display 20 or so reversible fns at once. From each gameState there is a reversible fn of each color (if it halts and has been observed) to/from another gameState, u can go back and forth. Example reversible fn, a certain number, add 3 if its even, else subtract 3 if its odd, else if its not an integer leave it as it is. Example reversible fn, if a certain gpu_circle exists (exactly, its whole contents), remove it, else add it. But id also want nonreversible fns, which would be arrows instead of symmetric edges. Generalize this to 3 edge types (like in wikib treeUI but add the evalsTo/red edge): L R EvalsTo, outgoing from each gameState or fn. Display these, not with text, but just as small circles. When mouseover them, display in the rectangle drag and drop editor andOr load the game state into dagball to roll balls on hills. Wikibinator203 license is GNU AGPL3 with a few extra permissions including classpath exception, and all the lambdas are derivative work of that universal lambda. https://twitter.com/DagBallGame/status/1717230564162654379',
'see comment in dagball html: TODO make this GPT4 API that lets users put in their own OpenAI API key into an iframe so Dagball and other websites can request to use it N times but cant get the key. When the new language is working, GPT4 should be able to build game content live.',
'tinyGlslCodeFromCirc = dagball.parseApeCode(apeCode).toApe().toTinyGlslCode().replace TODO edGroup.pointAtYXR',
'Add controls (hold a keyboard button while move mouse) to join 2+ circ.edsOut (dagball.Ed instances, the lines from circle perimeter) and hook them together after GPU poten() call to add the gradients of all that are connected together and hold their position and velocity together, as those should be stored in the circs.',
'Too many off-screen canvases (79). Every time you edit GPU code it makes a new one. Trying to clear the TinyGlsl.caches = {...} but have to delete them in some order or it breaks WebGL. see TinyGlsl.clearAllCache()',
'energy norming of potentialEnergy+kineticEnergy remaining constant, but thats kind of incompatible with velocityDecay and just moving stuff around with mouse. Will find something close to it. Maybe an alternative to scaledTanh on dagball.game.pos and dagball.game.vel.',
'make example dagball.CellmataState for rule110 convolutional scalar field, and bilinear interpolate it for balls to roll on and bend it, and for it to make the balls roll differently. Put this in a dagball.Circ',
`Fix this cycle where upOrLeftOfDiag is inside itself: (upOrLeftOfDiag trib fcfTriangleLoop {+
<(otherNodeVal float) [fcfDiag upOrLeftOfDiag]>
{f+= weightedSumCol {f* otherNodeVal [fcfDoubleTriangleWeights diag upOrLeftOfDiag]}}
{f+= weightedSumRow {f* otherNodeVal [fcfDoubleTriangleWeights upOrLeftOfDiag diag]}}
})`,
'Some of these todos are done. TODO move some to dagball.dones andOr update some',
'DagBall will support an exponential variety of scalable turing-complete manifolds. These are kind of random but simple basics of logic. DagBall will come with sparse 6SAT level swarms of bayes rule where each bayes6node fits in a WebGL2 GLSL kernel and can emulate any nand forest --https://twitter.com/DagBallGame/status/1708612525070131618 2023-10-1',
'hook in the code checker that outputs things like this for each var vars.freq_1:{"type":"int","read":true,"write":true,"isReadBeforeFirstWrite":false,"declared":true,"line":10}',
'circular wall rises around a ball and moves it around, as if grabbed by a circular hand and moved then released.',
'screw, sine wave, or sum of sine waves, etc.',
'constant curvy paths to roll down.',
'mostly flat platform with walls and obstacles in middle, that you tilt in 2d with 2 other dims.',
'elevator controlled by 1 dim.',
'needs 3d or at least 2 flat worlds overlapping (blue vs green per pixel etc). something like those scissorlike lines in screwballscramble game that ball rolls along.',
],
dones: [
//TODO list what ive done already
'FIXED 2023-11-12 by by copying the afMagnifyY afAddY etc code into ape code generator. Fix the coordinate system in <x$ ...> being pixel indexed instead of the coordinates circs and balls use. This switched coordinate system to pixels in the Ape.js upgrade ~2023-11-12.',
'FIXED 2023-11-12 by checking dagball.view.hasGpuCodeAndShouldUseIt(circ), ape code goes in the wrong 2 circs in Dagball089.html 2023-11-12-1220pET. Its windowed to a different circ than the code is in. why? circHeaders array?',
'DONE 2023-11-12. Use mergedApCalls to generate graphics from the circs that have ape: text. the display func has some arbitrary code just to test the graphics during the upgrade of moving dagball.Ape/Ap.Ape to its own file Ape.js (todo rename that to Ap.js cuz theres already an ape programming language?)',
],
/*
//stop browser debugger here
breakpoint: function(){
breakpoint;
},*/
debug: {}, //put vars here that are checked for in conditional-breakpoints
experimentalGradientMul2: 1, //if this is 1 it has no effect. vary it for wavefunction collisions to stop it from being so jumpy??
loadJsFile: path=>{
console.log('dagball.loadJsFile '+path);
document.body.appendChild(Object.assign(document.createElement('script'),{src:path}));
},
//displays it in the left textarea prefixed by "txt:" so it doesnt interfere with code or circs or balls etc. Unselects circ.
displayTxt: function(txt){
dagball.setSelectedCirc(null);
document.getElementById('mainEditTextarea').value = 'txt:\n'+txt;
},
//normally the string starts with "ape:" or "apeV1:" or "txt:" etc. This doesnt unselect circ so will overwrite its circ.text if selected.
setMainTextareaContent: function(string){
console.log('setMainTextareaContent: '+string);
let d = document.getElementById('mainEditTextarea');
d.value = string;
d.dispatchEvent(new Event('input'));
},
getMainTextareaContent: function(){
return document.getElementById('mainEditTextarea').value;
},
//changed this to a checkbox
//isDisplayGradientsAsBrightnessOfRectanglesOnBackground: false, //normal
//isDisplayGradientsAsBrightnessOfRectanglesOnBackground: true, //for testing
//gradientRectanglesHeightPixels: 20,
gradientRectanglesHeightPixels: 40,
//gradientRectanglesHeightPixels: 100,
/* If there are 400 dimensions, id normally do 401 GPU threads. Split that into 400/16=25 balls per GPU thread,
and get (400+1)*16 floats back instead of 400+1 floats back, and sum them to those exact (except for roundoff) 401 floats.
This way it will use all the GPU cores. Also maybe later automatically take stats on how fast it is with what levels of splitting.
make it a tuneable param for now, and leave tuning it for later.
In codeMaker and game.prototype.gradient, theres an outer loop that runs in GPU
(generates and gives code to Ap.js which calls TinyGlsl.js) for gradient/potens but not display.
{* ...} which im likely to rename apeType '*' to 'loop' etc {loop ...}, loops over numBalls.
If this splitOuterBallsLoopIntoMultipleGPUThreads is true then numBalls_i ranges
for example 0 to 15 in one thread, 16 to 31 in another thread, 32 to 47 in a thread, etc.
If its false, then it ranges 0 to numBalls_s-1 and puts that all into 1 float.
In the true example, ceil(numBalls_s/16) numbers returned from GPU to CPU get summed in CPU
and other than roundoff sum to the same 1 number as if this is false.
TODO what if its not divisible by 16? Branching logic in GPU is expensive.
Ill need either another apeType or i+ i/ imod pointer arithmetic to split numBalls in that loop.
Each ball takes 2 (if !isDoubleHeightmap) or 3 (if isDoubleHeightmap) of the floats/dimensions.
/*
{*
${isDisplayElsePotensForGradient?(
' (loopSize1TodoRemoveLoopInThisCase 1)'
):(
' numBalls'
)}
{+
<(heightASum float) 0>
<(heightBSum float) 0>
Theres also an inner loop over balls that only runs if balls are supposed to bounce on eachother,
which this is NOT about. The inner balls loop is this. It will be the same either way,
and it is used in display and physics/gradient/potens:
${doAllPairsOfBalls?(
` {* (otherBall copy numBalls) {+
${isDisplayElsePotensForGradient?(
' <(otherBallWeight float) 1>'
):(
' <(otherBallWeight float) {?: {i== otherBall numBalls} 0 1}>'
)}
<(otherBallY float) [balls otherBall 0%${floatsPerBall}]>
<(otherBallX float) [balls otherBall 1%${floatsPerBall}]>
<(ballOrDisplayYX_vs_otherBall_distance float) {fhypot {f- y otherBallY} {f- x otherBallX}}>
{f+= potenOne {f* otherBallWeight
{@addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap ballOrDisplayYX_vs_otherBall_distance}
}}
}}
See more comments in isSplitOuterBallsLoopIntoMultipleGPUThreads_ballBlockSize.
Also TODO this optimization: isSplitOuterBallsLoopIntoMultipleGPUThreads_ballBlockSize: 1, //this is simpler code to write, 1 index in outer balls loop and 1 gradient index per GPU thread.
*/
isSplitOuterBallsLoopIntoMultipleGPUThreads: false, //before ~2023-12-6 this opimization didnt exist. or you might go back to it during testing since its simpler.
//isSplitOuterBallsLoopIntoMultipleGPUThreads: true, //normal but this is an optimization trying to add 2023-12-6+
//This is how much of the outer balls loop happens per GPU thread if dagball.isSplitOuterBallsLoopIntoMultipleGPUThreads.
//If thats false, then its like this is a really big number and is not used (leaving whole outer balls loop as 1 block).
//For example, if this is 16 and theres 320 balls in !isDoubleHeightmap, thats 640 ball floats/dimensions plus the floats/dims for the curvy ground.
//16*2=32 so GPU returns 10 times more floats than if dagball.isSplitOuterBallsLoopIntoMultipleGPUThreads was false.
//
//Why would you want to use 10 times more GPU threads? A good gaming GPU has 1000-10000 cores, can do that many float multiply float in parallel.
//Each core has a little memory (such as 32kB) that may be its own or shared among a small group of cores, that par and loc Ap.js memories go in.
//Each core returns 1-4 floats in GLSL. In single heightmap dagball has them return 1 float. In doubleHeightmap 4.
//If you have 3072 cores and 640 dimensions, you can use at most 641 cores, and the others are wasted,
//unless theres so much memory used that they cant fit parSize+numCoresInGroup*locSize floats in the core group,
//in which case not all cores in that group could be used. In a nvidia chip this is called a warp nad is 32 cores
//and they must do the same opcode (such as multiply 2 floats) at the same time but this can in theory differ across multiple warps.
//In OpenCL1.2 I used this info to double the speed of matrix multiply, caching 2*32x32 floats in local memory per warp, see experiments in LazyCL.
//This software as of 2023-12-6 only uses WebGL2_GLSL, not OpenCL or WebGPU,
//but Ap.js might be upgraded later to do all 3 as different implementations of the same spec.
//The reason youd want to use 10 times more GPU threads is 641*10=6410 can use all the cores at once,
//or even better 641*64=41024 GPU threads (so they take turns on the 3072 cores in my GPU, for example). A bigger number of threads
//divides better into the number of GPU cores, doing less work per thread. The last cycle will use between 1 and all the cores,
//so average around half of them, so its better for such cycles to take less time and have more cycles.
//I use 800*600=480000 GPU threads for the display calculation, which returns 480000 floats 60 times per second.
//The 41024 threads in that example each do 10 times more work than a pixel display thread
//since it computes it for 640/64=10 balls/positions instead of just 1 (the pixel).
//So in theory, after this is working, can load that saved game dagball1701804687.142.json with the 479 balls that ran at 20 FPS
//seen in this video https://www.youtube.com/watch?v=J5Li524G6Us
//"DagBall 097 with 479 balls and 983 dimensions (mostly balls) slowed to 20 FPS - fixed stuck ball bug"
//and it should run at 60 FPS when dagball.isSplitOuterBallsLoopIntoMultipleGPUThreads and 20 FPS when thats false.
//The reason it stops at 60 FPS and doesnt go higher is im using that speed of HDMI screen and the browsers requestAnimationFrame does it.
//But I could go even faster in physics than graphics if so. I might turn it up to multiple physics cycles per video cycle,
//depending on speed available (TODO), so the balls would be able to move faster without destabilizing and moving through eachother and walls.
//
//Those 10 floats get summed by CPU into 1 float for all 320 balls, 1 per gradient dimension, so at (640+numCurveDimensions+1) floats either way.
//If !dagball.isSplitOuterBallsLoopIntoMultipleGPUThreads then it returns the (640+numCurveDimensions+1) floats directly. The +1 is neutralPoten,
//since the potential energy calculation computes 1 more float than gradient calculation which calls it,
//then does the calculus subtract and divide by epsilon: "gradient[i] = (potens[i]-neutralPoten)/this.floatEpsilon;".
//isSplitOuterBallsLoopIntoMultipleGPUThreads_ballBlockSize: 8, //this is likely the fastest, im guessing 2023-12-6, if the code was written for it
isSplitOuterBallsLoopIntoMultipleGPUThreads_ballBlockSize: 1, //this is simpler code to write, 1 index in outer balls loop and 1 gradient index per GPU thread.
//list of funcs to call with no params, in order they're added here, at the start of nextState then empty the list. Avoids modifying datastructs while graphics and physics is using them.
doAsap_: [],
scheduleCpuPaint_: [],
//acceleration toward game coordinate (0,0) (see dagball.aftrans to convert between game coordinates and canvas pixel coordinates).
//Every direction outward from that is up. You should probably draw (on dagball.bitpic) a mostly circular planet there to fall toward.
gravityToward00: 4,
//these are called in afterAfterPaint. u can paint directly onto canvas then as ByteRect or using canvas funcs like to paint text.
scheduleCpuPaint: function(func){
dagball.scheduleCpuPaint_.push(func);
},
/*
//null, else If you want all balls to attract or repel eachother, put that code here as Ap.Ape coded for a func/? of 4 floats ballAY ballAX ballBY ballBX.
//FIXME this is only for balls of constant size in singleHeightmap, not doubleHeightmap. In doubleHeightmap it has ballABal and ballBBal too, so 3 vars per ball,
//(and maybe also radius?). Not sure if will be more vars per ball.
//apCodePerPairOfBallsForSingleHeightmap: null,
apCodePerPairOfBallsForSingleHeightmap:
`(apCodePerPairOfBallsForSingleHeightmap? (ballAY float) (ballAX float) (ballBY float) (ballBX float)
<(float ballABDist) {fhypot {f- ballAY ballBY} {f- ballAX ballBX}}>
<(float ballABDist) {fhypot {f- ballAY ballBY} {f- ballAX ballBX}}>
<?: {fless ballABDist}>
)`,*/
//null, else If you want all balls to attract or repel eachother, bounce etc, put that code here as Ap.Ape coded for a func/? of 1 float (pairBallDist float).
addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap: null,
addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap:
`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{f* 8.05 {f** {f/ {fmax 0 {f- .07 pairBallDist}} .07} 2}}
)`,
/*`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{f* 1 -.1}
)`,*/
/*`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{f* .0000000005 {f** {f/ {fmax 0 {f- pairBallDist .02}} .02} 2}}
)`,*/
/*`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{+
<(minPairBallDist float) .04>
{funcReturn {f* 5.5 {f** {f/ {fmax 0 {f- pairBallDist minPairBallDist}} minPairBallDist} 2}}}
}
)`,*/
/*`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{+
<(minPairBallDist float) .04>
{f* 5.5 {f** {f/ {fmax 0 {f- pairBallDist minPairBallDist}} minPairBallDist} 2}}
}
)`,*/
/*`(addToEnergyPerBallDistanceCodePerPairOfBallsForSingleHeightmap? (pairBallDist float)
{+
<(minPairBallDist float) .04>
{?: {fless pairBallDist minPairBallDist}
{f* 5.5 {f** {f/ {f- pairBallDist minPairBallDist} minPairBallDist} 2}}
0
}
}
)`,*/
//call func() at the start of nextState, so it doesnt break the data structures while theyre being used.
//FIXME if any of these throws, then those added after it (before next call of nextState) are lost.
doAsap: function(func){
dagball.doAsap_.push(func);
},
//do and empty what was added by doAsap(()=>{...}).
doAsaps: function(){
let doAsap = dagball.doAsap_;
dagball.doAsap_ = [];
for(let func of doAsap){
func();
}
},
//make tab key type a tab instead of tabbing over to next dom node.
//TODO tab over all selected lines, and shift+tab less (remove a tab) from all selected lines.
mainEditTextareaOnKeyDown: (textarea,event)=>{
if(event.key == 'Tab'){
console.log('mainEditTextareaOnKeyDown Tab event='+event);
event.preventDefault();
let start = textarea.selectionStart;
let end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start)+'\t'+textarea.value.substring(end);
textarea.selectionStart = textarea.selectionEnd = start + 1;
}
},
//Normally you dont use this, but if theres a hard to track down bug this can make test cases,
//though it only knows the GPU inputs and outputs, not if they're correct or not.
//Can set this to getTestCase and it will call getTestCase(theTestCase)
//after dagball does its next potential energy physics calculation in GPU.
//The test case should be compatible with ApGpuTester.js and maybe come in its own html file,
//depending on the listener since wrapping it in a html file would be done there.
makeTestCaseOfNextGpuPotensCall: null,
//If false, circs are independent of eachother even if they overlap, except that the same ball can roll on multiple circs at once which affects gradient.
//If true (normal), then the dagball.Ed's (the lines from circs) from multiple circs can be pointed at the same (y,x) to create a dagball.EdJoint there
//which holds those float vars / dimensions together, as if its 1 shared var between the circs.
//isUpdateEdsByEdJoints: false,
isUpdateEdsByEdJoints: true, //normal
//used in roundToEdSnapGrid. FIXME adjust this. FIXME this might not work far away from (0,0) cuz float has 24 digit bits of precision. Theres some max radius of game. adjust it.
//snapGridSize: 2**-6,
snapGridSize: 2**-4,
minAftransMagnify: 5,
maxAftransMagnify: 10000,
speedMouseChangesMagnify: .8,
//how many times farther apart the lines from the circs (dagball.Ed's) does EdGroup.pointAtYXR spread them,
//times the (a little more than, FIXME) minimum they can be spread so that dagball.snapGridSize doesnt put 2 eds/lines from same EdGroup at same (y,x)
//which would cause their float values (ed.pos and ed.vel) to be held together as if they were 1 ed/floatVar which is how circs share float vars/dimensions.
//pointAtYXRScale: 1,
pointAtYXRScale: 2.5,
codeHelpText:'Each array exists in par, loc, or both. [...] uses its default, or {parPtr ...} or {locPtr ...} chooses.'+
' Use parMem for game state. Use locMem for temp vars that are different in each GPU thread.'+
' TODO All parMem\'s get automatically converted to locparMem\'s for computing {size {par}} dimensional gradient but stay as parMem in display code.'+
' Each circle has its own code (in textarea below). To see how they\'re combined, search for "codeMaker" in view source of this html file.',
//depending on isDoubleHeightmap, a different 2 of dagball.view.mergedApCalls (which has 4 keys, 4 apcalls, of which 2 get created) are used.
isDoubleHeightmap: false, //simpler, can display more pixels, but cant make bridges or circuit crossings. 1 heightmap if false, 2 if true.
//isDoubleHeightmap: true, //TODO this should be normal but is not built yet 2023-11-13.
loadWikibinatorAsyncRightAfterBoot: false,
potentialEnergiesForDisplay_usesApesInCircs_elseSimpleTestCode: true,
displaySelectedEdLinesJitteryOnFromSide: false, //hold lines still even if selected
//displaySelectedEdLinesJitteryOnFromSide: true, //normal. so you can see which EdGroup is selected if theres multiple EdGroups in same circ. All those selected eds eds do this.
//optional instance of dagball.BitPic that can for example be a 5000x5000 1-bit-per-pixel pic of walls you bitpic and open areas, that balls bounce on.
//If null, doesnt do this physics. If nonnull, TODO its physics is added to poten (as in gradient calculation) after GPU computes potens, per ball.
//TODO in wholeGameState store this as compressed using dagball.BloomTree.
bitpic: null,
bloomtree: null, //when click 1 of 2 buttons it copies between between dagball.bitpic and dagball.bloomtree
//maxRadiusOutToReadOrWriteInBitpicRR: 50, //sanity check. it should be alot smaller than this. gets very slow if bigger.
maxRadiusOutToReadOrWriteInBitpicRR: 2000, //2023-12-31 made this really big cuz i dont want to limit it anymore, cuz im using usually small but sometimes very big zoomed out paintbrush
//paintbrushRadiusForBitpic: .05, //FIXME, is this in game coordinates (where 1.0 is about 80 pixels) or bitpic pixel coordinates, or what?
paintbrushRadiusForBitpic: .15, //FIXME, is this in game coordinates (where 1.0 is about 80 pixels) or bitpic pixel coordinates, or what?
//paintbrushRadiusForBitpic: 1, //FIXME, is this in game coordinates (where 1.0 is about 80 pixels) or bitpic pixel coordinates, or what?
//paintbrushRadiusForBitpic: 10, //FIXME, is this in game coordinates (where 1.0 is about 80 pixels) or bitpic pixel coordinates, or what?
min_paintbrushRadiusForBitpic: .001,
max_paintbrushRadiusForBitpic: 30,
//readSmoothYXR_r: 5,
//readSmoothYXR_r: .15,
//readSmoothYXR_r: 50,
//readSmoothYXR_r: 10,
//readSmoothYXR_r: 4,
//readSmoothYXR_r: .5,
addExampleBitPic: function(optionalHeight, optionalWidth){
//let wallPoten = 1.5;
//let wallPoten = .5;
let wallPoten = 50;
let wallThick = 5;
//let wallPoten = 1;
//let wallPoten = 4;
let h = optionalHeight || 100;
let w = optionalWidth || 100;
//let h = 300;
//let w = 300;
//let h = 3
//let w = 3;
//let numInts = Math.ceil(h*w/32);
//let ints = new Int32Array(numInts);
let numBytes = Math.ceil(h*w/8);
let bytes = new Uint8Array(numBytes);
//let af = new dagball.SimpleAftrans(0, 0, 1, 1); //FIXME different magnifyY and magnifyX
//let magnify = 2**-9;
//let magnify = 2**-7;
let magnify = 2**-5;
//let magnify = 2**-3;
//let magnify = 1;
//let af = new dagball.SimpleAftrans(0, 0, magnify, magnify); //FIXME different magnifyY and magnifyX
let af = new dagball.SimpleAftrans(-magnify/2, -magnify/2, magnify, magnify); //FIXME different magnifyY and magnifyX
//let b = dagball.bitpic = new dagball.BitPic(wallPoten,wallThick,h,w,ints,af);
let b = dagball.bitpic = new dagball.BitPic(wallPoten,wallThick,h,w,bytes,af);
/*for(let y=0; y<h; y++){
for(let x=0; x<w; x++){
//let isWall = y!=x ? 1 : 0;
let isWall = 1;
b.writeYX(y,x,isWall);
}
}*/
b.fillRandom();
},
saveFile: (fileName, contentType, text)=>{
var blob = new Blob([text], {type: contentType});
if(window.navigator.msSaveOrOpenBlob){
window.navigator.msSaveBlob(blob, fileName);
}else{
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = fileName;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
},
log_tinyGlslCurveCode: true,
//hideMouseCursorOnCanvas: false,
hideMouseCursorOnCanvas: true,
//moved to checkbox
//showGlslCodeOfApesInRightTextarea: false,
//showGlslCodeOfApesInRightTextarea: true,
logApeDebug: false,
addFakeNumbersToGradientForTestingSoYouCanSeeItAccelerate: false, //normal
//addFakeNumbersToGradientForTestingSoYouCanSeeItAccelerate: true,
getCheckboxIds: function(){
//FIXME search for them using document.querySelector? how about only those that have a certain css class dagballOptionCheckbox?
return 'experimentalGradientMul2 isDisplayBallText isDisplayBallCircles displayWavefunctionCollisionsAsBackground varEqLogs pauseDagball doDiffeq isShowWhichCircleIsSelected doAllPairsOfBalls doStatisticalCollisionsBetweenWavefunctions isDisplayGradientsAsBrightnessOfRectanglesOnBackground isDisplayCircOutlines isDisplayEdges isDisplayEds isDisplayDetailedEdsAlways showGlslCodeOfApesInRightTextarea'.split(' ');
},
/*getNumberBoxIds: function(){
return 'baseVelDecay gradientMul'.split(' ');
},*/
//FIXME do this in dagball.View instead of the dagball object?
//the local game state, which (TODO) may include copies of some parts remote game state. Its meant to be massively multiplayer and very sparse,
//such as 1 game world might include a gigabyte of unique GPU code in a million circs of 1kB of code each.
gameStateToMap: function(){
let ret = {type:'dagball_wholeGameState', openThisJsonFileWith:'https://github.com/benrayfield/DagBall', circles:[], balls:[]};
ret.bitpic = dagball.bitpic ? dagball.bitpic.toMap() : null;
for(let circ of dagball.circles){
ret.circles.push(circ.toMap());
}
for(let ball of dagball.balls){
ret.balls.push(ball.toMap());
}
ret.uiOptions = {chk:{}, num:{}};
for(let chkId of dagball.getCheckboxIds()){
ret.uiOptions.chk[chkId] = document.getElementById(chkId).checked;
}
/*already included these in some of the .dagball/json files with the lines below this comment: for(let numId of dagball.getNumberBoxIds()){
ret.uiOptions.num[numId] = document.getElementById(numId).valueAsNumber;
}*/
ret.baseVelDecay = document.getElementById('baseVelDecay').valueAsNumber;
ret.gradientMul = document.getElementById('gradientMul').valueAsNumber;
ret.aftrans = dagball.aftrans.toMap();
//ret.readSmoothYXR_r = dagball.readSmoothYXR_r;
return ret;
},
checkboxIdToMap: function(id){
//TODO opt_ or num_? opt as in option.
//return {type:'dagball_keyval', mutid:'num_'+id, val:document.getElementById(id).checked?1:0};
//return ['f$'+id, document.getElementById(id).checked?1:0];
return ['z$'+id, document.getElementById(id).checked?1:0];
},
numberBoxIdToMap: function(id){
//return {type:'dagball_keyval', mutid:'num_'+id, val:document.getElementById(id).numberValue};
return ['f$'+id, document.getElementById(id).valueAsNumber];
},
//each json in the Set can be turned on/off independently, though not all combos will work. Its sparse.
//This is the new way to save/load 2024-1-6+ but its not working yet. Experimental. See Dagverse.js.
//The dvid (dagverseId, a hash id, in base64 (dagverses specific base64 digits) is immutable. Some objects also have a mutid (id of mutable object).
//There can be at most 1 object on screen and local physics sim at once of each mutid. There can be many dvids of the same mutid.
//The ball.id and circ.id fields are mutids as of 2024-1-6 but todo change the id field to mutid and maybe add dvid field in the map?
//
/* Example of part of returned Set of Maps (to get the keys do DV.mapToId(map)):
j$wfqkGanrcFR1XBPsRRH9dBwqg9csqhPkx8S9VAHeawk:{"id":"sBall10","mutid":"sBall10","influence":1,"y":1.9880467887749667,"yv":0.6308392621722826,"x":-0.35867122771158544,"xv":0.5910713271788934,"red":166,"green":74,"blue":15,"displayText":"K"}, //TODO norm it in DV
Dagball122.html:9694 j$PWaozcRNqOPyGU_lfnmxRJ5vSF5pv7PRKyjSnleCdV3:{"id":"sBall11","mutid":"sBall11","influence":1,"y":0.06731662543840464,"yv":-0.7718966201954237,"x":0.18840549773995424,"xv":-0.307551462464403,"red":151,"green":75,"blue":254,"displayText":"L"}, //TODO norm it in DV
Dagball122.html:9694 a$f$experimentalGradientMul2_0:["f$experimentalGradientMul2",0], //TODO norm it in DV
Dagball122.html:9694 a$f$isDisplayBallText_1:["f$isDisplayBallText",1], //TODO norm it in DV
Dagball122.html:9694 a$f$isDisplayBallCircles_1:["f$isDisplayBallCircles",1], //TODO norm it in DV
Dagball122.html:9694 a$f$displayWavefunctionCollisionsAsBackground_0:["f$displayWavefunctionCollisionsAsBackground",0], //TODO norm it in DV
*/
gameStateToMaps: function(){
//list of maps that each can be a Dagverse object, be turned on/off separately. Each has (or can be derived deterministicly) 1 dvid and at most 1 mutid.
//Order of this list doesnt matter. TODO choose one deterministic. Its meant to be a set. Maybe I should just use a set.
//let ret = [];
//Set of maps or lists, whatever kind of object it is. ['ball5',fourNumbers...] is a small partial update of mutid 'ball5'.
let ret = new Set();
//to keep different games of dagball separate from eachothers physics and constraint solving etc, though you can still copy/paste between them.
//This is like a game room or a chatroom that between 1 and a million players (or practically will likely be around 1-50 for a while) use together
//so dont have to do sparse fading in/out circs and balls yet so work within the 1000 floats/dimensions on GPU at once limit, non-sparsely, for now (2024-1-6).
ret.add(['g$namespace',dagball.namespace]);
//let ret = {type:'dagball_wholeGameState', openThisJsonFileWith:'https://github.com/benrayfield/DagBall', circles:[], balls:[]};
//ret.add({type:'opt', mutid:'str_openThisJsonFileWith', val:'https://github.com/benrayfield/DagBall'});
ret.add(['g$openThisJsonFileWith','https://github.com/benrayfield/DagBall']); //g prefix means strinG. a means array of floats. j means json/{}/[].
//TODO allow multiple bitpics if they dont disagree on any pixel, counting transparent as not making a claim
//about that pixel (of any powOf2 size powOf2 aligned square).
//ret.bitpic = dagball.bitpic ? dagball.bitpic.toMap() : null;
for(let circ of dagball.circles){
ret.add(circ.toMap());
}
for(let ball of dagball.balls){
ret.add(ball.toMap());
}
//ret.uiOptions = {chk:{}, num:{}};
for(let chkId of dagball.getCheckboxIds()){ //FIXME should i just search for all the checkboxes? Maybe i should
//have a list to exclude (checkboxes i might make later that i dont want to be part of Dagverse game state,
//not sure why id want that, but its possible), instead of to include?
ret.add(dagball.checkboxIdToMap(chkId));
//ret.uiOptions.chk[chkId] = document.getElementById(chkId).checked;
}
/*already included these in some of the .dagball/json files with the lines below this comment: for(let numId of dagball.getNumberBoxIds()){
ret.uiOptions.num[numId] = document.getElementById(numId).valueAsNumber;
}*/
//ret.baseVelDecay = document.getElementById('baseVelDecay').valueAsNumber;
//ret.gradientMul = document.getElementById('gradientMul').valueAsNumber;
ret.add(dagball.numberBoxIdToMap('baseVelDecay'));
ret.add(dagball.numberBoxIdToMap('gradientMul'));
//for(let domId of 'baseVelDecay gradientMul'.split(' ')){
// ret.add(dagball.numberBoxboxIdToMap(domId));
//}
//ret.aftrans = dagball.aftrans.toMap();
let afMap = dagball.aftrans.toMap();
//Theres only 1 of these per player/user but there will be lots of these in multiplayer, so not sure if this is a good name,
//as it implies theres only 1, but maybe different computers will just fork the dagverse/multiverse to have it always be their local aftrans?
afMap.mutid = 'aftrans$main';
ret.add(afMap); //FIXME make sure it has a mutid, instead of id (old name of mutid). 2024-1-6 aftrans has no id or mutid. TODO create a mutid?
//ret.readSmoothYXR_r = dagball.readSmoothYXR_r;
return ret;
},
//FIXME do this in dagball.View instead of the dagball object?
gameStateToJson: function(){
return JSON.stringify(dagball.gameStateToMap());
},
//FIXME do this in dagball.View instead of the dagball object?
loadGameStateFromMap: function(map){
if(map.type != 'dagball_wholeGameState'){
throw new Error('map.type='+map.type+' but expected dagball_wholeGameState');
}
if(!map.circles || !map.circles.length){
throw new Error('No map.circles or its empty, map='+JSON.stringify(map));