-
Notifications
You must be signed in to change notification settings - Fork 0
/
Dagball.html
16562 lines (14768 loc) · 855 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/V.js"></script>
<script src="lib/LeastSquaresLstmQlearn.js"></script>
<script src="lib/Dagverse.js"></script>
<!--script src="lib/Gob.js"></script-->
<!--script src="lib/Dagfield.js"></script-->
<script src="lib/nacl-fast.js" title="dchest_tweetnacl-js-1.0.3_2024-2-8.zip"></script>
<script src="lib/TinyGLSL.js"></script>
<script src="lib/Ap.js"></script>
<!--todo use NsatDesignToolGpu with up to 40 vars to help me design Wikibinator305 instead of Axgob. script src="lib/Axgob.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.
//2024-5-10 lib/Axgob.js will be the next version of Wikibinator, with optimizations for gaming.
//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
//(multiple physics cycles (doPhysics) per 60 FPS display cycle if fast enough).
/* UPDATE: the V array upgrade (theres a checkbox) avoids compiling again when you just change float literals in lib/Ap.js (ape) code since it puts those in as data instead of code, consuming some
of the up to 1000 (1024?) floats that can go in a GLSL uniform array (inside a GPU core),
so when you edit ape code of a neuralnet (saves/nnet*.dagball files),
and if that something-V-something checkbox is checked, and then push ; key to finish your edit
so it turns from light blue textarea back to white (TODO dark mode checkbox),
then for every physics cycle (60+ per second) you have changed specific floats
in the GPU memory of every GPU core at once. Every core gets its own copy of those floats,
and you see the neuralnet change as a 2d heightmap on screen.
If you change any other parts,
it is near instant for simple code but 20 seconds for a neuralnet.
For circles (each containing custom GPU code) whose preferCpu checkbox is checked,
it compiles them to javascript (CPU) instead, which happens near instantly
but can handle much fewer calculations so use less dimensions per circle
and use alot more circles. GPU is for number crunching. CPU is for sparse.
Balls roll on all circles of moving heightmap-like terrain. The circles are summed
at each pixel to determine the height of the heightmap, which is really a 2d cross-section
of a many dimensional scalar-field that has all the dimensions of all the circles/customCodes
together. Circles can share dimensions by making 2 lines touch at a 2d point.
Each line is a float variable/dimension in a custom ape code, which come in named arrays
(of the variable name of the array in the code in the circle).
Different circles have different numbers of lines.
Any 2 lines can be joined, whether they're from the same circle andOr multiple circles.
When they're joined, their position and velocity are held equal,
and gradient is sum of their individual gradients.
This is a SAT solver as in NP-Complete, though often doesnt find the exact solution,
it solves toward lower total potential-energy of all constraints.
This is also a fourier solver and many other kinds of math,
whatever you can fit in the textarea while a circle is selected to edit its GPU/CPU code.
If you define a neuralnet prediction algorithm, but you do not define a training algorithm,
it gets autodiffed 1 level deep between input and output,
and if there happens to be 15 unrolled RNN time steps between that,
then the neuralnet still gets automatically trained.
Theres video of that happening in saves/*349.349.dagball which contains the neuralnet.
That neuralnet is live trained at last 1 training batch per video frame
cuz training batches happen in a physics cycle.
Balls are 2d training data. The lines you can join between circles are the AI model
which can contain neuralnets and other shapes.
In this system the set of all neuralnets of a certain kind and size etc,
is a constant high dimensional shape, and by running dagball's physics engine on it,
the neuralnet is automatically trained by accelerating by negative gradient of position.
You'll find gradient* field names in Ball and Ed (circ.edsOut is a list of Ed,
and ed is a dimension/floatVar), for example.
The dagball game's level editor is the text editor
and checkboxes etc on the left of screen,
and the canvas on the right (2/3 of screen).
You use keyboard shortcuts (click var= checkbox to see what key does what),
by holding 1 or more keys while moving the mouse.
Mouse left button selects a circle or ball.
Mouse right button unselects. While sected, a circle can be edited.
A circle is selected if mouse is just over it. You only left click it to keep the
circle selected even when mouse moves off it, then right click to end that,
but those clicks must be on the game area not the edit controls on the left.
On the left, it uses normal webpage controls.
Type in a text box. Edit numbers in a box with clickable up/down arrows. etc.
There are 10 quickload and 10 quicksave buttons.
Its like the old game emulators. Whatever you built, whatever it became after playing,
and whatever options you've changed, is frozen into a json file.
The quicksave/quickload buttons use browser cookies (LocalStorage object).
Theres also 2 buttons to save/load from json/dagball file. (nnet*.dagball for neuralnets).
If you have trained a neuralnet by moving the balls to reshape it,
those neuralnet weights will be in the quicksaves andOr *.dagball files.
It gives you the files for download, generated inside the html,
or keeps them in cookies.
...
2024-5-27
First, write the high level steps here. Then organize them. Then copy it to items in mmMain so can check them off when finish each. Write the steps all the way up to a 50 player game happening at dagball.com where any 1 player acts as host of their game and can stream the dimension pos'es and vel's and game levels (*.dagball file) thru it. Dont do any axgob cuz that upgrade is for later and will get into various rabbitholes of software design and sync. Thats a second goviral. Dagball by itself is first goviral.
Existing dagball uses 1 physics shader and 1 graphics shader and is limited to 1000 dims (dimensions). neuralGoo is an upgrade to dagball (dagballNeuralGooUpgrade) which will practically extend that to maybe 5000 dimensions at once and unlimited dimensions off screen not being used at the time that it can swap in and out. Or maybe just 2500 dimensions depending how fast it runs. The important thing is it becomes sparse, cuz I need more content than 1000 dims. But im unsure if I can have more than 500 dims of manually created circs (such as sine waves that move in phase and angle, fractals, etc) that run in GPU. That will be 1 gooGroup. I could have a second gooGroup with another 500, and a third gooGroup with another 500. I could load alot of those, not sure how many, but ive had up to 80 off screen canvases at once. The problem is they take a few seconds to compile that much dimensions. 20 dimensions is often .1 second to compile, which is an ok loading time to happen every 30 seconds as players move across the huge game world. But 20 seconds is not. The neuralnets take 10-20 seconds to compile the first time, then near instant cuz GLSL remembers them even across browser tabs. I'll want to compile new ones of those infrequently but use LOTS of intstances of the 1 or few neuralnets i compile. Also theres an experiment waiting to do in TinyGLSL, when its the same sizes, to reuse canvas, GL object, and a few other things instead of making a new canvas every time, but that might only make it slightly faster, or possibly make it alot faster in some cases, so dont count on that. Plan to work within the compile time limits by reusing fewer compiles of GPU, and by simpler circs run on CPU. The simpler circs on CPU will have to do the same kinds of calculations as the GPU circs. They'll both be writte in Ap.js/ape code (dont call it just ape cuz theres another programming language with that name, call it Ap.Ape or Ap (todo use google trends with compare to estimate popularity of new names, later maybe, not part of this neuralGooTodos2024-5-27+ task). So basically I'm about to upgrade to dagball levels (each is a *.dagball file) that have 700-2100 dims of manually created circs, in blocks of at most 700 at once so theres space for 300 balls per near area, or maybe limit everything to 450 so overhead of 100 doesnt mess with 2 of them 100+2*450, but i think 700 is a better limit cuz i get better neuralnet. So 700*n manually created gooGroups, and unlimited balls but at most 100 balls computed at once (and maybe 2 kinds of balls, one as curveGrab and one normal, ignoring axgob balls (Field manaRefillRate ball55) for example. No axgob in neuralGooTodos2024-5-27+, thats for later And I will sample in 2d to find where its likely to have steep gradients, statistically spread curvegrabball/goosyncball there (2 names for possibly the same thing), then do gradient as usual but in gooGroups number of GPU calls, 1 per gooGroup combined with 100 curveGrabBalls andOr normal balls (might mix curveGrabBalls and normalBalls or do them in separate GPU calls, will have to see how much lag that adds and tune params). gooGroups will interact with eachother only thru normalBalls and curveGrabBalls and EdJoints, NOT thru [pairs of gooGroups with pseudorandom 2d points] like I had planned cuz that needs about someOtherSmallConstant*(kindsOfGooGroups^2)/2 number of compiles, vs just smallConstant*kindsOfGooGroups number of compiles. There will be 3 kinds of apes (compiled shaders) instead of 2. The original 2 are physics and graphics, all game objects at once. The new 3 kinds are: gradfind (estimated gradient finder by absVal of dotProduct of gradient with random epsilon length vector), gradeep (gradient in deep detail), and hillfind (the display code but its a weightedAve of gooGroups. Each gooGroup has a window (var) at each 2 point, normally 0 outside its circ and 1 inside its circ, but it could be defined as a 2d bellcurve in that circ cut off at edges of circ or an easeInOut shape by radius so its 0 at perimeter and 1 at center, or theres various other possible shapes, but I think for now 2d bellcuve, hard circle, and maybe squashing and tilts of those (so pole-like smooth oval) should be enough, and practically im gonna leave it as hard circ for now cuz thats what i have and individual circs can make themselves smooth within that circ if they want. So those 3 ape kinds are: gradfind, gradeep, and hillfind. [UPDATE: 2024-9-27, these became the "5+ kinds of eval", including evalGpuMain evalCpuDiffeq evanCpuMain, look up the others, and as of that date, some are working and some are not, and some of the *.dagball files work and some do not, so theres bug fixes to do so the old game content still works which will be a sign that the redesign is done] I might merge gradfind and hillfind by running each pixel (450x600 resolution) on a slightly different world state, computed inside shader, based on a seed for pseudorandomness given to GPU from CPU once per video frame, and use the difference in adjacentp pixels for estimating where steep gradients are. BUT NO, gradfind and hillfind CANT BE MERGED cuz they compute different things. Gradfind computes squared error of difference of potens/hills that partially overlap, which might be computed as stdDev^2 of weightedSums (weight is .influence var at 2d point of each gooGroup partially overlapping there). When they agree what poten should be at that 2d point, stdDev is 0, and ave is that poten. So to compute gradfind, I need the separate hills (monochrome pic with float32 brightness, 1 such pic per gooGroup) then to make a 450x600 float array to compute stdDev of them at each pixel, in 2 steps, first compute weightedAve at all the pixels, then compute weightedStdDev at each pixel, then square those stdDevs, then spread the curveGrabBalls/gooSyncBalls statistically where those squared errors (stdDev^2) are, then call gradeep once per gooGroup_and_100_balls. If theres 600 balls then would call that gooGroup on 6 groups of such balls and sum the 6 gradients to get the combined gradient. Similarly sum the gradients for all the gooGroups, merge in Edjoints as usual (when 2 circs have lines that touch eachothers ends, each touch point of 1 or more eds is an EdJoint, which holds those position and velocity equal, merging multiple dimensions into a single dimension called an EdJoint). Where does the epsilon length random vector fit in? Gradfind is to make a ballpark estimate of where steep gradients are likely to be, before doing the detailed very precise gradient calculations at 100 2d points (with 700 other dimensions they share) sampled from that ballpark estimate. I have written a mistake. It should not be stdDev^2 cuz that assumes the gooGroups can always sync with eachother. If they cant sync, then gradfind would keep trying by putting alot of balls there but keep failing. Instead, I want to put the balls where theres steep gradient of the loss function. Not gradient of the hills/poten but of the loss. The loss is that all gooGroups should agree at all 2d points on what is the hill/poten, weighted by gooGroup.influence (like circ.influence in existing dagball code 2024-5-27, which is like a volume knob for a circ to turn its hills steeper or flatter, and when it reaches 0 influence its the same as that circ does not exist). So theres some details to work out on how to fit the epsilon/sqrt(numDims) (or is it multiplied by that sqrt?) length vector (where +epsilon is normally added in locparMem as a slight variant of parMem for gradients as usual, but instead of +epsilon at 1 dim its a random epsilon length vector that part of is added to each dim in that gradient loop in GPU, a vector made by pseudorandom seed so it doesnt cost floats to store it. The details to work out are how to combine such random vectors from multiple gooGroups to estimate where the gooGroups disagree with eachother in the 450x600 pixels.
..
try this: for the same pixel at the same 1/60 second (video cycle), its the same epsilon length random vector for all overlapping pixels there, 1 from each gooGroup that partially overlaps there, which practically will usually be between 0 and 10. That way, can compute exact poten there at 2 points, and each point has all the gooGroups (that overlap there), then just divide the poten difference by vector length (and maybe scale by mul or divide by sqrt(numDims)?), take absVal of that, and use that as the output of gradfind at that 1 of 450x600 pixels. Make it be a different pseudorandom vector at each pixel_and_videoCycle so it trades spatial resolution for precision of steepness of nearby gradients since it can look at more dimensions (random direction in 1000d) at once that way.
...
Since each of 450x600 pixels will compute potential-energy at 2 world states that differ by a random epsilon length 1000 dimensional vector (sparse gradient max 1000 dimensions at once) and that will happen at 60 FPS, thats 450*600*2*60=32,400,000 world states computed per second
*/
/*alert(`Its ok. I just raised physicsCyclesPerVideoFrame from 1 to 4 2024-1-22 and wrote code in a circ to make certain
hills steeper using tanh andOr exp of potenCirc$ though tanh is better cuz doesnt go far out of range making screen go black.
Im back to making game content. Continue.
TODO fix readSmoothYX_onDisplayPotens so balls dont bounce so chaoticly. also it has hardcoded numbers in it.
Make it visible where the "wall blobs" (see checkbox) are forming and when.
Make it not wall vs nonwall in readSmoothYX_onDisplayPotens but use the gradual potens, and just search it within given distance
and combine them somehow.
makeSecondBitpicOfWherePotenGreaterthan0.7Etc_displayDagballWallsSlightlyColored
so balls will hard bounce on the fractal hills etc instead of smoothly sliding over them when ball is moving mid to fast speed.
This will solve the problem thats blocking me from making game content. It will let me make content that squeezes balls tight in 2d curvy spaces.
There will likely be problems where the poten moves too fast, forms at and all around a ball thats already there, but I'll just have to work thru it by tuning this physics model. Remember the ball that went so fast in the video it went thru a thick wall and was bounced around inside the wall and quickly ejected by the wall (either that or by its existing speed) but its direction fast changed in the wall. This is probably cuz jit bounces against the 1 closest wall mini block so is chaotic. So likely as long as the circs are designed to be smooth enough this wont be a problem.
Also I might want a float[4kX4k) etc to cache the last outputs of display from GPU since zoom can vary, and need to interpolate or sample to match them.
`);*/
//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.
`);*/
/*
UPDATE: "Math model of DagBall is map<map<vector1000,scalar>,scalar>" is still true but theres a simpler form of it
where each map<vector1000,scalar> has 1 extra dimension called influence.
map<vector1000,scalar>.influence is 0 to not exist, 1 to exist, or gradually between or could be any finite value.
This allows adding and removing game objects, that each are a map<vector1000,scalar>,
is done by setting 1 dimension per object. Any other dimensions that object contains are ignored by influence==0.
Therefore instead of map<map<vector1000,scalar>,scalar>, its map<dimensionId,scalar>.
Also you need 2 map<dimensionId,scalar>, one for position and one for velocity,
or call it a map<dimensionId,complexNum> as position+i*velocity.
Only 1 level deep, a dimensionId can require other dimensionIds be loaded in memory,
those within the same game object.
A dimensionId is either the hash of a json, or is one of the float variables in it,
and maybe should use dimensions for gamepad inputs and other streaming vectors in general.
By streaming vectors I mean live time-series of any sparse parts of map<dimensionId,scalar>,
which would be viewed in the game as whoever is near a 2d area of the game computes that area,
and the many computers fit that together by leastSquares and maybe some kind of gametheory
for those who try to compute the wrong next state of that area of the game
instead of it being just the normal difficulties of merging things at different milliseconds
of calculating it, different float32 roundoff, etc. I can use GPU exactly deterministicly
but its alot slower calculation, except in some cases its equally fast.
A truly decentralized game world, held together by math. Someday.
For now 2024-9-27 dagball is single player on 1 computer. Its about to expand.
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.
//2024-9-27 these are written but not read. They have no effect.
// Dagball is single player on 1 computer so far and is about to expand.
// Theres mutliple kinds of ids and its not ready to use this yet.
// But this is not far off from what I'm going for.
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;
var C = null; //selected dagball.Circ, set in dagball.setSelectedCirc, for convenience on browser console. In dagball code, use dagball.selectedCircs()[0].
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: [
//2024-9-27 i have not been much using these todos and dones lists for long time, a few things here and there maybe.
'2024-5-9 remove the false && from if(false && existingEdGroup && existingEdGroup.eds.length == targetNumEdsInThisGroup) but see comments about detailed code need to write',
'2024-2-24-4pET the fadeTiles checkbox exists but is not hooked to any code. Code it to make dagball.influenceAtYXR be 1 everywhere if NOT fadeTiles, so can track down bugs in the tile system, since its hard to see whats in GPU if it might just be invisible (influence 0 or near 0) but still computed in GPU.',
'2024-2-24+ makeButtonToMoveViewAroundFastToPreloadGPUCompilingForWhatsNearby this is about the sparseWorld checkbox',
'2024-2-[22..24]+ //and physics affected by it (FIXME or even farther if its ed lines are outside the circ)',
'2024-2-[22..24]+ doesnt work with 0 circs: "--- It appears the problem is at some time having 0 circs in Ap.js, as in this code i found in browser debugger [[[{doLast (balls locparMem (numBalls 11) (floatsPerBall 2)) (circHeaders locparMem (numCircs 0) (headerFloatsPerCirc 4)) (aftrans locparMem {4})...]]], which is a bug ive found before in a different form that deleting the last circ that runs in GPU causes it to crash. 2024-2-22-540pET. I confirmed this by making sure a circ was displaying before turning on sparseWorld, and it worked until I scrolled away from it."',
'2024-2-22+ makeSparseWorldCheckboxMultiplyByInfluenceAFTERSigmoidortanhetcLimitingEachCircNOTBEFORESoItFadesOverLongerDistance',
'2024-2-22+ Fix alwaysUpdateViewInNextState to work when the set of things to display changes related to sparseWorld for all object types, cuz otherwise i have to check it to make it update which circs are displayed.',
'2024-2-22+ The sparseWorld checkbox works only when sparseWorldOnlyInfluence checkbox is checked (so sparse in influence but all objects exist in GPU so not actually sparse in a useful way). Error[dagverse/:2594 Uncaught unkown apeType: 0]. hasGpuCodeAndShouldUseIt is giving the correct answer of should circ be computed in GPU or not EXCEPT i want to delay that change until the next physics/graphics/nextState cycle so different parts of the calculation all see the same set of circs. The dagball.doAsap(func) scheduling function can do that, but ill need to store the data in the circ itself (maybe use its circ.exists var? or make a new var? cuz .exists is meant to mean remove it completely from the memory, leaving it only on peer to peer network andOr saved *.dagball files. Maybe call it softExists or something like that?). Also see the alwaysUpdateViewInNextState bug about this. --- It appears the problem is at some time having 0 circs in Ap.js, as in this code i found in browser debugger [[[{doLast (balls locparMem (numBalls 11) (floatsPerBall 2)) (circHeaders locparMem (numCircs 0) (headerFloatsPerCirc 4)) (aftrans locparMem {4})...]]], which is a bug ive found before in a different form that deleting the last circ that runs in GPU causes it to crash.',
'2024-2-22+ use circHeadersContents.push(circ.computeInfluence()); in case of not compileCircHeadersUsingLocMem',
'2024-2-22+ use circHeadersContents.push(circ.computeInfluence()); in case of compileCircHeadersUsingLocMem',
'2024-2-22+ use circ.computeInfluence()',
'2024-2-22+ use ball.computeInfluence() similar to circ.computeInfluence()',
'2024-2-22+ //gradually between. TODO make this smoother? Its a straight angle between flat 0 and flat 1, //and I dont like it having corners. Should it use the math called "ease in out"? It would slightly weaken it //therefore needing sparseDistFar to be a little bigger to have same size of view near the edges, //but extend the parts where its near 1 out a little past sparseDistNear. //This is a research path to be explored. return 1-(dist-sparseDistNear)/(sparseDistFar-sparseDistNear);',
'2024-2-21+ DV.Fastree has nothing to do with "approximately-maximum-likelihood phylogenetic trees from alignments of nucleotide or protein sequences" which I see is also called fastree. I just meant "fast tree".',
'2024-2 (has always been this way, TODO fix anyways) Theres still some webGL security stuff (dont want one guys content overwriting anothers in GPU memory, etc). The DAG is coming. Its not a sparse game world yet, will be soon.',
'include whole nacl software, licenses, etc from dchest_tweetnacl-js-1.0.3_2024-2-8.zip the license is the Unlicense "This is free and unencumbered software released into the public domain." and few more paragraphs, from https://github.com/dchest/tweetnacl-js',
'//doesnt unselect circ if any was selected. FIXME its getting replaced by the usual circ.text right after this so this isnt displaying. displayTxtQuiet: function(txt){',
'if(map.nn){ //cuz of cycle circ.nn.circ. FIXME should nn (a RbmCircBridge) lack the circ ptr and take it as a param in its relevant funcs?',
'When dagball scales up it will naturally tend to create alot of WebGL2_GLSL context objects being invalidated by pointer out of range in GPU. WebGL already sandboxes this, but it does create a delay to create another context object. For lower lag I need to [en.wikipedia.org Formal verification - Wikipedia] .. and by it naturally creating out of range pointers, I mean that it is not running proof checker on the simple algebra expressions like y*width+x. ... That should in theory result in it safely running unlimited variants of custom GPU code forking and merging with eachother freely across many computers and people using those computers (peer to peer) where the network survives and sorts out useful from non-useful info.',
'physicsCyclesPerVideoFrame_targetMinFPS: 59, //FIXME if the screen has a max FPS below this, it will go to physicsCyclesPerVideoFrame trying to raise it.',
'//same string returns same js lambda, whatever apeFuncJs returned. FIXME clear that cache if theres too many? dagball.cachedApeFuncJs = function(text){',
'//FIXME should use .mutid and get rid of .id (see Dagverse.js)',
'//TODO optimize by when line is partially on screen, start and end i at different integers.',
'//let yy = this.aftrans.reverseY(gameY); //FIXME why is it 2 reverses? This looks wrong. Might have done it wrong multiple places to get it right together?',
'max call stack exceeded on the base64 func string.fromcharcode something 2024-1-30, but only when try to save new random bitpic, already its bytes, about 300kB. its part of javascript, dont know whats going on, but its working when the bitpic is not random, is the racetrack i painted.',
'dagball.BitPic.prototype.paintOntoPotens(addHere, addHereHeight, addHereWidth, aftrans){ //FIXME starting with the slow way so i have code to refactor and know it works, but FIXME update it to the fast way.',
'//FIXME 2024-1-30 this is likely to break code that assumes par and loc are same size. Its an upgrade that was planned during design of par and loc.',
'//FIXME these might vary across gamepads. Use dagball.actionControls to make controls //customizable by user, but will need a UI for it and somewhere to save the controls mapping.',
'//2024-1-21 havent used dagball.game.pos for a long time. TODO remove oThisBall?',
'//FIXME since didnt call dagball.afterEveryCanvasDomEvent(event); (cuz this happens every video frame, not on events), //the controlsChanged code might not work for it? dagball.update_prev_directControls(); is farther below in this same nextState func.',
'let canvasScale = Math.sqrt(dagball.canvasScaleY*dagball.canvasScaleX); //ugly hack. FIXME',
'add <input type=checkbox id=doKnobGradients checked><label for=doKnobGradients>doKnobGradients</label> to wholeGameState etc',
'detailedEds are displaying on the last selected circ even if none is selected, or is it selected when it shouldnt be? the circle icon on circs perimeter goes away when mouse is not near any circ, but the detailedEds still display 2024-1-16.',
"//FIXME hardcoding knob dragging to dagball.controlsChange('selectLockAOn') cuz thats been left/main mouse button for a while as of 2024-1-16.",
"unless controls mapping changed (FIXME): draggingEdSliderKnob: null, //null or the dagball.EdSliderKnob being dragged by mouse. dagball.controls('selectLockAOn') is 1 when left/main mouse button is down, unless controls mapping changed (FIXME)",
'let add = mouseChangeAlongEdLine*5.5; //FIXME why this constant?',
'Merge coordinate systems. some things are in game coords (about 100 pixels per 1.0 distance in game at normal zoom, but zoom varies extremely) and other things are in canvas pixels coords, it appears 2024-1-16: edSliderKnobOrNull.val += 0.11756163013873532 mouseY=3.4458233121285233 knobY=178.0632613180356',
'connect <input type=checkbox id=mouseDragsKnobs checked> and other checkboxes (those this isnt done for yet) into wholeGameState, and the new way of saving where everything is its own {} object.',
'remove ed.velDecay and ball.vd or ball.velDecay cuz its computed somewhere else instead',
"if(dagball.controlsChange('selectLockAOn') == 1 && !edSliderKnobOrNull){ //FIXME what if selectLockAOn is not connected to mouseButton0/leftButton?",
'knob.isSelected = knob===edSliderKnob; //FIXME since knob.toString() returns knob.val (a number), would == return the wrong thing here?',
'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: [
//2024-9-27 i have not been much using these todos and dones lists for long time, a few things here and there maybe.
//TODO list what ive done already. alot of stuff in the "todos:" list probably should be here as of 2024-2-23?
'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?)',
],
mouseColorRGB: [.1*255.999, 1*255.999, .3*255.999], //[redByte, greenByte, blueByte] but maybe fractions not integer byte?
/*
//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??
//This makes a kind of line appear on the screen that points from one circle to another.
//Most of its length is the same color as the FROM circle, and the part near the TO end is the same color
//as the TO circle, and then theres a little empty space cuz it does not touch the TO circle.
//Theres keyboard controls to create, delete, and other kinds of editing of those Edge's.
//Thats Edge, not Ed. Ed is a floatVar/dimension.
//
//as of 2024-5-24 edges (dagball.Edge) exist in the demo that starts with dagball.html but were not used anywhere else and have not been saved in any *.dagball files.
//They were for future expansion, and now is [UPDATE: 2024-9-27 i havent been doing anything more with neuralnets fitting together and am focusing on the "5+ kinds of eval" redesign which should scale dagball up by having most circs be preferCpu=true (checkbox is checked when that circle is selected). neural goo is delayed cuz theres more scaleable prototypes to build first, and scaling to the most number of players at once is a big part of what will make dagball fun, its a swarm game.] the time to do that expansion for gooGroup: and gooSync circ types.
//[[
//Dagball is getting a new layer soon that will have tiny neuralnets training eachother so they continuously cover a 2d game world,
//each near some 2d area partially overlapping other tiny neuralnets. Will have some stuff other than neuralnets, but neuralnets are
//easier to scale. The new dagball layer will probably use these DAG edges up 2 more layers. First is to group them into a gooGroup,
//so the curvy hills add together within the group. Then on pairs (or more?) of groups to use least-squares so they agree on the
//curves where they overlap.
//]]
edgeEdit: {
viewEdgeFromId: null, //set by viewEdgeFrom. id of a circ.
viewEdgeToId: null, //set by viewEdgeTo. id of a circ.
//set by viewNextEdgeType viewPrevEdgeType or viewEdgeTypeText. Example edgeTypes: any, like, true, gpucircExistVote, gpucircInfluenceMedianVote.
//Will likely add some for the circ.text starting with 'gooGroup:' and 'gooSync:' but those are circ texts not edgeTypes. They will use edges.
viewEdgeType: 'any',
},
//get checkbox value true/false. dont call this in a big loop cuz thats slow. call it once outside that loop.
//false if checkbox doesnt exist (happens near boot or if its a *.dagball/json file from an old version).
//If param optionalValueIfNotFound is given, it would normally be true or false (defaults to false)
//but you might give another object type such as null or NaN or 'notFound' etc if you're gonna check for that.
chk: (domId,optionalValueIfNotFound)=>{
let dom = document.getElementById(domId);
if(dom){
return dom.checked;
}else{
return optionalValueIfNotFound!==undefined ? optionalValueIfNotFound : false;
}
},
//like chk but for number boxes. Returns optionalValueIfNotFound (if param exists) else NaN if not found.
//Reason it may not be found is different versions of dagball have different number boxes, checkboxes, etc.
num: (domId,optionalValueIfNotFound)=>{
let dom = document.getElementById(domId);
return dom ? dom.valueAsNumber : (optionalValueIfNotFound!==undefined ? optionalValueIfNotFound : NaN);
},
//like chk but for text boxes. Returns optionalValueIfNotFound (if param exists) else NaN if not found.
//Reason it may not be found is different versions of dagball have different number boxes, checkboxes, text boxes, etc.
txt: (domId,optionalValueIfNotFound)=>{
let dom = document.getElementById(domId);
return dom ? dom.value : (optionalValueIfNotFound!==undefined ? optionalValueIfNotFound : '');
},
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);
dagball.displayTxtQuiet(txt);
},
//doesnt unselect circ if any was selected. FIXME its getting replaced by the usual circ.text right after this so this isnt displaying.
displayTxtQuiet: function(txt){
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.
//TODO merge this with dagball.setTextareaText(nextText,true), or have this call that with true.
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;
},
//returns 1 of the list items, where goal(item)->score is higher (or equal, preferring lower indexs in list to break ties) than any other list item.
//Returns null if list is empty or if the best score is nonpositive.
bestPositiveInList: function(list, goal){
let best = null;
let bestScore = 0;
for(let i=0; i<list.length; i++){
let score = goal(list[i]);
if(score > bestScore){
best = list[i];
bestScore = score;
}
}
return best;
},
//default_textareaEventUpgrades: true, //normal, TODO
default_textareaEventUpgrades: false, //for testing compiler lag problems 2024-5-10+
default_semicolonCompiles: true,
//default_transformFloatValsToVArray: false, //was normal 2024-5-14
//default_transformFloatValsToVArray: true, //should become normal asap. is normal 2024-5-20 cuz fixed nan bug (need to absval the base of pow even if exponent is 2 cuz might be 2 plus/minus epsilon with GLSL optimizations)
default_transformFloatValsToVArray: false, //2024-9-3 changed this to false cuz of redesign but TODO make it true by default later
//you can type the name of an edGroup aka ape array name here and it will show only those
default_edIncludeRegex: '^(.*)$',
//after edIncludeRegex, excludes from that, ape array names you want to exclude such as the 'hdr' array containing (z,y,x)
//inputs that gets auto added to every cpuCirc if it doesnt already have a hdr, or the V array (not displayed anyways cuz
//does not go in circs, just the generated code around them, for GPU). The V array eds wont be displayed either way.
default_edExcludeRegex: '^(hdr|V)$',
cachedRegex_: {},
cachedRegex: regex=>(dagball.cachedRegex_[regex] || (dagball.cachedRegex_[regex] = new RegExp(regex))),
//true if matches edIncludeRegex and not matches edExcludeRegex
isDisplayEdsForName: name=>{
return dagball.cachedRegex(dagball.txt('edIncludeRegex')).test(name) && !dagball.cachedRegex(dagball.txt('edExcludeRegex')).test(name);
},
//other teams are RED GREEN or BLUE. //const RED = 0, GREEN = 1, BLUE = 2, ALPHA = 3; ive been using for canvas colors.
//If red green and blue balls exist they normally play some variant of rock paper scissors by touching eachother to change eachothers team.
defaultTeam: ALPHA,
defaultBaseVelDecay: .6,
defaultGradientMul: 2, //FIXME should be 1?
defaultGpuCompileNumTilesOutward: 1,
defaultTileSize: 4,
defaultShowGroundHeightOnMouse: false,
//speedMouseChangeCurveGrabMid: 1,
//speedMouseChangeCurveGrabMid: 100,
speedMouseChangeCurveGrabMid: 400,
//speedMouseChangeCurveGrabLowAndHigh: 1,
//speedMouseChangeCurveGrabLowAndHigh: 100,
speedMouseChangeCurveGrabLowAndHigh: 400,
//changed this to a checkbox
//isDisplayGradientsAsBrightnessOfRectanglesOnBackground: false, //normal
//isDisplayGradientsAsBrightnessOfRectanglesOnBackground: true, //for testing
//gradientRectanglesHeightPixels: 20,
gradientRectanglesHeightPixels: 40,
//gradientRectanglesHeightPixels: 100,
/* UPDATE 2024-9-27, theres a checkbox to do more GPU threads like this, and it worked last I tested it,
but I havent tested it since the "5+ kinds of eval" redesign started and am not sure if it would work or not. TODO.
...
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.
*/
//was moved to checkbox: 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. Those codes call dagball.doAsap(()=>{...}).
doAsap_: [],
doOnNextEvent_: [],
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,
gravityToward00: 0, //now that im doing rockPaperScissors id rather have no gravity. but its supposed to be stored in wholeGameState json.
//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}>
)`,*/
//This is an "ugly hack", a workaround for the bug that there must be at least 1 circ in GPU. TODO fix it then remove this.
//see never0CircsInGPU checkbox (which is checked and locked that way by being dom node disabled
//(2024-2-22-740pET im experimenting with that checkbox not disabled, TODO),
//since i didnt make the option to remove the circNever0CircsInGPUJson from dagball.circles as of 2024-2-22, TODO).
//Hopefully this will stay as dagball.circles[0]. TODO fix the bug so it can still run GPU with 0 circs,
//such as balls can still bounce on eachother which is done in GPU.
//This is a HUGE dagball.Circ that covers the whole game area and adds nothing to poten. It has no effect on physics,
//except possibly if there was a bug in EdJoints as it has 1 edjoint to (0,0).
//Its invisible except if you zoomed out far enough to see its circle outline, ed lines (one of them to (0,0), etc.
circNever0CircsInGPUJson: '{"id":"circNever0CircsInGPU","mutid":"circNever0CircsInGPU","type":"dagball_circ","syncType":"swarm","lockCirc":false,"lockText":false,"lockEdgesOut":false,"isPubkey":false,"priority":1,"circExists":true,"influence":1,"y":0,"x":0,"r":10000,"red":200,"green":200,"blue":200,"isSelected":false,"text":"ape:(do {abc locparMem (1)} <potenCirc$ 0>)","edgesOut":[],"edsOut":[{"type":"dagball_ed","y":0,"x":0,"pos":0,"vel":0,"sliders":[],"slidersFunc":null,"velDecay":0,"edGroup":null}],"dimsOut":{},"nn":null}',
set_circNever0CircsInGPU_enabled: function(enabled){
dagball.circles = dagball.circles.filter(c=>(c.mutid!='circNever0CircsInGPU')); //remove all circs whose id is circNever0CircsInGPU, if any. (should never be more than 1)
if(enabled){
let circNever0CircsInGPU = dagball.mapToCirc(JSON.parse(dagball.circNever0CircsInGPUJson)); //make a new one
dagball.circles.unshift(circNever0CircsInGPU); //add at index 0 and slide other circs up
}
},