:Class DuckDash : MiPage ⎕ML←1 :Include #.HTMLInput ⍝ ⎕RL←0 ⍝ sets completely random start. Any other value repeats. ⍝ These fields are for future use when we want to allow the user ⍝ to define the size of his board and delay between generations :field rows←23 ⍝ board rows was 23 :field cols←97 ⍝ board columns was 55 :field duckn←324 ⍝ 12320 is 1st duck # ⍝ DD number ducks in duckdash 2600 268+75=343 :field duckp←0 0 ⍝ DD duck row col positions :field ducka←⍬ ⍝ 2 3 4 97 98 99 ⍝ ?175⍴2600 ⍝ duck adoptions initial=⍬ :field duckf←⍬ ⍝ DD duck finishers in order :field duckstop←1 ⍝ DD stop after finding # of winners does not really work :field delay←100 ⍝ DD delay in ms between generations was 50 :field yelBeg←'<Yel style="color:rgb(255,255,0);">' ⍝ changes txt/ducks to Yellow :field yelEnd←'</Yel>' ⍝ ends color change :field redD←'<rred style="color:rgb(255,0,0);">' :field public htmlBoard←'' ⍝ the html returned when the user edits the board :field public event←'' ⍝ the event returned by APLJax :field public what←'' ⍝ the element that had the event returned by APLJax :field initialized←0 ⍝ flag to indicate if game has been initialized :Field Public Ans←'' ⍝ Name of edit field for output of adopted ducks :Field Public Action←'' ⍝ All action buttons have this name ∇ b←lifegen b;n;r;f ⍝ DD lifegen input & output is board (1↑¨duckp)+←¯2+?(⍴(⊃¨1↑¨duckp))⍴2 ⍝ DD new row positions for random ducks f←(0≥1⊃¨duckp)/⍳duckn ⍝ check to see if new finishers. :If 0<⍴f ⋄ duckf←∪duckf,f[(⍴f)?⍴f] ⋄ :End ⍝ If tie add them in random order b←rows cols⍴0 ⋄ n←0 ⍝ DD delete old board positions n=duck# ⍝ check for finishers and put in random order :For i :In duckp ⋄ n+←1 ⍝ DD update board and check for wins :If 0≥1⊃i ⋄ duckp[n]←⊂rows,2⊃i ⋄ b[rows;2⊃i]←1 ⍝ restart finisher duck :Else ⋄ b[1⊃i;2⊃i]←1 ⍝ place regular duck on board :EndIf :EndFor :For i :In ducka ⍝ mark adopted ducks on board last so they on top r c←i⊃duckp ⋄ b[r;c]←2 ⍝ if row=0 change it to rows :EndFor ∇ topc←{r←⍺|⍵ ⋄ ((r=0)/r)←⍺ ⋄ r} ⍝ ⋄ x←cols topc x ⍝ show duck on b ∇ Init ⍝ initialize pattern and board :Implements constructor :Access public ⎕RL←0 ⍝ random start each time. any other number repeats the previous random order :If (2022 6 11≡3↑⎕TS)^(2≤4⊃⎕TS) ⋄ ⎕RL←13 ⋄ :End ⍝ woodley uses UTC time 10 hrs ahead of HI generations←0 ⍝ keep track of the number of generations pattern←3 3⍴0 1 1 1 1 0 0 1 0 ⍝ our initial pattern duckp←rows,¨duckn⍴⍳cols ⍝ DD duck row,col start positions. Some may be on top of each other. board←rows cols⍴0 ⋄ board[rows;]←cols↑duckn⍴1 ⍝ DD init board with duckn 1's in last row. board[rows;cols topc ducka]←2 ⍝ put adopted ducks on top marked as 2's prev←⍬ ⍝ previous generation stasis←0 ⋄ duckf←⍬ initialized←1 ⍝ indicate we've been initialized ∇ ∇ html←Render req;html;ctrl;edit :Access Public ⍝ :If ~initialized ⋄ Init ⋄ :EndIf ⍝ if not initialized, initialize the board DoAction req.Use'JQuery' req.Script lifeScript delay html←'h2'∘Enclose'Actual Race Saturday June 11,2022 12:00pm Rotary Duck Dash ',(⍕duckn),' Ducks. Watch Now & See Who Wins.' ⍝ add links to rotary club website & facebook and Duck Jokes pdf's html,←'<li><a href="https://rotaryclubofhawaiikai.org/" target="_blank">Rotary Club of Hawaii Kai: Website</a>' html,←'<a href="https://www.facebook.com/rotaryclubhawaiikai" target="_blank"> FacebookSite</a>' html,←'<a href="/jbgames/data/duckjokes.pdf"> DuckJokes1</a>' html,←'<a href="/jbgames/data/duckjokes.pdf"> DuckJokes2</a></li>' html,←'<a href="/jbgames/duck3.dyalog" target="_blank">Play:deDUCKtive Educational Thinking Game</a>' html,←'<a href="/jbgames/DuckHide.dyalog" target="_blank"> Play:Find Where Ducks Are Hiding Game</a></li>' html,←'<br><a href="https://www.givsum.com/opportunities/hawaii-kai-ducky-dash-2020-bb8b6f6c0" target="_blank"> Adopt your ducks to play this game</a></li>' html,←BR,'Enter your adopted duck #''s ie 20 to 30 Then Click <b>Check</b> Button:' html,←'Ans'Edit Ans 100('title="xxx"') html,←'Action'Submit'Check' ⍝ A button named 'Action' with Caption 'Check' ⍝ define the control buttons ctrl←Button'Start' 'onclick="runLife()"' ctrl,←2 SP Button'Continue' 'onclick=''$("body").trigger("nextGen")''' ctrl,←2 SP'stop'Button'Stop' 'onclick="stopLife()"' ctrl,←2 SP'reset'Button'Reset' ⍝ ctrl,←2 SP'edit'Button'Edit' ctrl,←2 BRA 2 SP Button'Video' 'title="Conway''s Game of Life in APL" onclick=''$("#video").slideToggle("slow")''' ctrl←'div id="ctrl"'Enclose ctrl ⍝ define the editor buttons edit←'div id="editor" style="display: none;"'Enclose 2 BRA('save'Button'Save'),2 SP'cancel'Button'Cancel' html,←ctrl,edit html,←2 BRA'div id="board"'Enclose formatBoard board html,←'iframe id="video" width="480" height="360" src="http://www.youtube.com/embed/a9xAKttWgP4" frameborder="0" allowfullscreen style="display:none;"'Enclose'' html←'div align="center"'Enclose html html,←req #.JQ.On'body' 'nextGen' '' '#board' html,←req #.JQ.On'#reset,#cancel,#edit' 'click' '' '#board' html,←req #.JQ.On'#save' 'click'('htmlBoard' '#board' 'html')'#board' html←req('post'Form)html ⍝ Put a 'submit' form around it req.Return html ∇ ∇ html←APLJax req;html;toggleButtons ⍝ if the request is from APLJax :Access Public html←'' toggleButtons←JS'$("#editor,#ctrl").toggle();' ⍝ jQuery to toggle button sets :Select event :Case 'click' :Select what :Case 'save' board←(⍴board)⍴{'@'=∊('span'∘≡¨⍵[;2])/⍵[;3]}⎕XML htmlBoard html,←toggleButtons :Case 'edit' ⍝ req.Response.(NoWrap HTML)←1((formatEditBoard board),toggleButtons) :Return :Case 'cancel' html,←toggleButtons :Case 'reset' ⍝ "reset" button clicked Init ⍝ reinitialize the board :Else ... ⍝ unknown click? this should never happen :EndSelect :Case 'nextGen' prev,←⊂board ⋄ prev←(-5⌊⍴prev)↑prev ⋄ board←lifegen board ⋄ generations+←~stasis :Else ... ⍝ unknown event? this should never happen :EndSelect ⍝ xxxx html,←yelBeg(bb←rep formatBoard board)yelEnd ⍝ color the board and ducks :If duckstop≤⍴duckf ⍝ DD old version was --> :If (⊂board)∊prev stasis←1 html,←BR'h4 align="center"'Enclose (⍕⍴duckf),' Ordered Finishers=',(⍕duckf) ⍝ html,←BR'h4 align="center"'Enclose'Stasis achieved after ',(⍕generations),' generations.' html,←JS'$("#stop").click();' :EndIf ∇ formatBoard←{('pre style="background-color:DodgerBlue;font-family:Monospace;width:',(⍕10×cols),'px;"')Enclose,' ⍋⌹'[1+⍵],(rows 2)⍴CRLF} rep←{x←⍵ ⋄ ⍺←'⌹' '<redD style="color:rgb(255,0,0);">⌹</redD>' ⍝ xxxxtopc ⍝ topc←{r←⍺|⍵ ⋄ ((r=0)/r)←⍺ ⋄ r} ⋄ x←cols topc x ⍝ show duck on b ((x=1↑⍺)/x)←1↓⍺ ⋄ ⊃,/x ⍝ replace symbol with red font ⍝ try: 'D' 'DA' rep 'D⍋⍋⍋⍋⍋ ⍋⍋D⍋⍋' ⍝ to get:'RX⍋⍋⍋⍋⍋ ⍋⍋RX⍋⍋' } ∇ r←lifeScript delay ⍝ build the script to run life in a timed loop r←'var t; var running=0; var delay=',(⍕delay),';',CRLF r,←'function nextGen(){$("body").trigger("nextGen"); modified=0; t=setTimeout("nextGen()",delay);}',CRLF r,←'function runLife(){if (!running){running=1; nextGen();}}',CRLF r,←'function stopLife(){clearTimeout(t); running=0;}',CRLF r,←'$(function(){$("body").on("click","span", function(e){$(this).html("-"==$(this).html()?"@":"-")});});',CRLF ∇ ∇ DoAction to←{(⍺-1)+⍳1+⍵-⍺} ⍝ to enter adopted ducks ie: 30 to 33 becomes 30 31 32 33 :Select Action :Case 'Clear' ⋄ Sum←'' ⋄ Ans←'' :Case 'Check' ⍝ determine #'s that could make the Sum entered :Trap 0 ⋄ ducka←Ans←⍎⍕⍕Ans ⋄ Init ⍝ your adopted ducks to watch :If (duckn<⌈/Ans)∨(∨/Ans≤0) ⋄ Ans←' Out of range number. 1-',⍕duckn ⋄ :EndIf :Else ⋄ Ans←' Invalid numbers. Try again.' :EndTrap :EndSelect ∇ :EndClass