From a2c4164a65d6a7233e9f37da89e7fd66ad0ec3ed Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Thu, 5 Dec 2024 10:29:36 -0700 Subject: [PATCH] Clean up docs. I hope this doesn't break the web site. --- docs/TODO.md | 8 + docs/_config.yml | 6 - docs/_layouts/default.html | 29 - docs/_site/TODO.html | 36 - docs/_site/assets/css/dirtbags.css | 151 --- docs/_site/assets/images/grunge.png | Bin 6761 -> 0 bytes docs/_site/assets/js/figures.js | 5 - docs/_site/assets/js/tanks.js | 310 ----- docs/_site/history.html | 117 -- docs/_site/index.html | 70 - docs/_site/running.html | 89 -- docs/_site/standie.svg | 260 ---- docs/_site/thanks.html | 37 - docs/_site/token.svg | 1897 --------------------------- docs/assets/css/dirtbags.css | 151 --- docs/assets/images/grunge.png | Bin 6761 -> 0 bytes docs/assets/js/figures.js | 5 - docs/assets/js/tanks.js | 310 ----- docs/forf.html.m4 | 13 - docs/history.md | 19 +- docs/intro.html.m4 | 147 --- docs/intro.md | 72 + docs/nav.html.inc | 10 - docs/procs.html.m4 | 74 -- docs/procs.md | 47 + docs/running.md | 73 -- 26 files changed, 128 insertions(+), 3808 deletions(-) delete mode 100644 docs/_config.yml delete mode 100644 docs/_layouts/default.html delete mode 100644 docs/_site/TODO.html delete mode 100644 docs/_site/assets/css/dirtbags.css delete mode 100644 docs/_site/assets/images/grunge.png delete mode 100644 docs/_site/assets/js/figures.js delete mode 100644 docs/_site/assets/js/tanks.js delete mode 100644 docs/_site/history.html delete mode 100644 docs/_site/index.html delete mode 100644 docs/_site/running.html delete mode 100644 docs/_site/standie.svg delete mode 100644 docs/_site/thanks.html delete mode 100644 docs/_site/token.svg delete mode 100644 docs/assets/css/dirtbags.css delete mode 100644 docs/assets/images/grunge.png delete mode 100644 docs/assets/js/figures.js delete mode 100644 docs/assets/js/tanks.js delete mode 100644 docs/forf.html.m4 delete mode 100644 docs/intro.html.m4 create mode 100644 docs/intro.md delete mode 100644 docs/nav.html.inc delete mode 100644 docs/procs.html.m4 create mode 100644 docs/procs.md delete mode 100644 docs/running.md diff --git a/docs/TODO.md b/docs/TODO.md index 6fd40ff..e80c02b 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -10,5 +10,13 @@ Requests ======== * Merge devdsp fixes (https://github.com/devdsp/tanks/commits/master) + +Done +==== + * Fix leaderboard + +Won't Fix +======= + * Read sensors from "sensors" and not "sensor[0-9]" diff --git a/docs/_config.yml b/docs/_config.yml deleted file mode 100644 index 199bf78..0000000 --- a/docs/_config.yml +++ /dev/null @@ -1,6 +0,0 @@ -defaults: - - - scope: - path: "" - values: - layout: "default" diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html deleted file mode 100644 index 94e08b5..0000000 --- a/docs/_layouts/default.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - -{% if page.scripts %}{% for js_file in page.scripts %} - -{% endfor %}{% endif %} - {{ site.title | default: site.github.repository_name }} by {{ site.github.owner_name }} - - - -

{{ page.title | default: site.title }}

- -{{ content }} - - - - diff --git a/docs/_site/TODO.html b/docs/_site/TODO.html deleted file mode 100644 index af7313a..0000000 --- a/docs/_site/TODO.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - by - - - -

To-Do List

- -

BUGS

- -

Requests

- - - - - - - diff --git a/docs/_site/assets/css/dirtbags.css b/docs/_site/assets/css/dirtbags.css deleted file mode 100644 index 6a86e06..0000000 --- a/docs/_site/assets/css/dirtbags.css +++ /dev/null @@ -1,151 +0,0 @@ -/**** document ****/ - -html { - background: #eed url(/assets/images/grunge.png) repeat-x; -} - -body { - font-family: sans-serif; - color: #112; - padding: 10px; - max-width: 700px; -} - -/**** heading ****/ - -#title { - text-transform: lowercase; - font-size: 1.6em; - padding: 3px; - margin: 0 0 1em 2em; -} - -#title:before { - color: #999; - letter-spacing: -0.1em; - content: "Dirtbags: "; -} - -/*** left side bar ***/ - -nav h2 { - display: none; -} - -nav ul { - list-style: none; - text-align: center; -} - -nav li { - display: inline; -} - -nav li a { - text-transform: lowercase; - font-size: 0.9em; -} - -nav li + li:before { - content: " | "; -} - - -/**** body ****/ - -a img { - border: 0px; -} - -a { - text-decoration: none; - color: #2a4; - font-weight: bold; -} - -a:hover { - color: #ddc; - background: #2a4; -} - - -h1, h2, h3 { - color: #464; - letter-spacing: -0.05em; -} - -.readme { - background-color: #ccc; - margin: 1em; -} - -pre { - background-color: #ccc; - border: solid #888 2px; - padding: 0.25em; -} - - -th { - vertical-align: top; - text-align: center; -} -td { - vertical-align: top; - text-align: right; -} - -p { - line-height: 1.4em; - margin-bottom: 20px; -} - -hr { - border: 1px solid #444; -} - -dt { - white-space: pre; - background-color: #333; - padding: 5px; - border: 2px solid green; - border-bottom: none; - font-weight: bold; -} - -dd { - border: 2px solid green; - margin: 0px; - padding: 5px; - background-color: #282828; -} - - -/**** special cases ****/ - -.wide { - max-width: inherit; -} - -.figure { - margin: 0.5em 1em; - float: right; - font-size: small; - text-align: center; -} - -.scoreboard { - background: #222; -} - -.scoreboard td { - height: 400px; -} - -#battlefield { - border: 2px solid green; -} - -.solved { - text-decoration: line-through; -} diff --git a/docs/_site/assets/images/grunge.png b/docs/_site/assets/images/grunge.png deleted file mode 100644 index 9a8c41a59bdff7795373467cb677a9a49cf8b04e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6761 zcmW+*c{tSX*H);nE!mT7k+FpAGcsh$K9fBX6&YKYnJhE5EZLGh!pA77NkxV1k+nt) z8vDKsV;Sq%hKaY|`^UM?a^L5i=X$Q^kLO$`=@!g{i~S-y6B84cnW>Qt6BDaC6Vs{D zQ_TM&F_to?|EV*#EbWZ{>64R_x1&Xq|EyDwZD6)cHx@@c|K~igFfn3EWED02=dcBu zI-&p78vdW0GLS6@{TDp@*v!iK>-4=&~YB{e+T0dAWz{8Gl%*`Z;qLn||07x$wx{TPz| zul(=S@X=h@)hUPIC~`-Z%Gt3x3B1hXmbTNG=r@XD<0TN=EBQY;)6#|O`Or2k%bkEO zCMO_}oxlw3VeNMAc9qeDafpxriv~69uYQJAvu6|L93%vWqQnxJS5f zLKfPAqizUlG*yiGy!KkOOS2_i>KILhusthWVEJ=?UyeKP@ToKlk>y@6VR@(2o{TW43nhoWVE~tklDb<>*pt`v%HniNKFv^lvhd&68GUmuSm#|4}D)nWAlt{V>Q|yo+>h`qB^_ z(xWZhNnn-=CWVo8R9y^F+G@j$g6ZgR56e3+QTG;^Zl~gg7{0GJ;K}O=KFu;ze`FqI zgPkbIt=?U97*&X>ywUU_q=}%%e(DW-@A-oD zdxZ=EgOy)wdAL4Vwf<}J+G40PXfJGNKlsq?&FUQ~?kIm^YM}Yop}c^DtjsKoec-2= zygW)9c>e|~JGo8x3}D}v*`eGSu%!JS-^onCFna4XQYs5M|5ie@?z(Gr)vT&tgMQLc zLba;E^e(Hl3stjn*d7!qi@}ES{#ZXNv|IdDG^>SfVLPcCDG4-O9Bg{)vbRSEr&&3g z5F1|J_T#-!O|JTO-AI~%sj!r{QMo#=aPaGnM688r^}@WC1@!Htt)l<=P|6yOIiv}gBvPP|3_9b!#4iQq`pPNa_z|9nG zwtirHaE^qwC4WI5;!n;_>qdC&KWsbDX;g6AKjEA>FGgLjZ^q2PR)Sx=4CYjaw2uYt z?yJ^`A+@{oW{s~y z;$*Ms+D>yse>94Z{b|LK*vNNdKZOH9O2FiZ2oaMSs^Nsa`k#O>UKBnd&`!VgY4- z-!aR_vu>Uflk7nar470VQ920xkvf-bYcWGkA_0w-Que~;$FjjC*KdE*uW zET5EAFWYRbOGXDAs@fT?AJQHeh*akonz8o_`0 zFF!h5t=r=K4b6A??3EPD;eZq}a0)K$zu!k)E=BLE$L&Ro6(+mRb5Vb?;3ZvhqTrqu zk0#@fhkTQCLq}q|$SI4Tq(BQTpjw|>d-S{oPZki*_xP@X5k-c0V7!GLjJ=r68R<;M zWNxCm;8V}J`&v@pw1P(OJiaT3x zi!!dhT>=XC%57B1B&|UwnkH9!F1V@GG+tRWjWW6bNGgi(okN?vudx$u#UwuLbjrpp z3|aTGqIfUvcPoynY{2guHb;?Cs_8@3_uRa2V6TSsK^X$js<@2 zz+1xxNb!enz@i5{A$|=?37f_!^75^R&c9dEZ_5W@_XTe*6@~auPjMLEkOUoqc9+u} z%I>@Kh!D(bX_@35zfk2c5g7vfNj&j$jNgyZ9R^s>AaBc^X`>NfEY0AxF{dG70)QrM zsc&tx5AP11oP5v1jHhXwEo;1L{f;nz|4wH?sHMs&_Be^~SQErkI zn-|48`&EVmK_L%hDcIs2QzF;bTt4DS@m*WxwF<7O+`xAr+lV{$t6(=LRr>YK^^j2HKCkc1=+sF@<;-{I+9gGkV;XDvy=!;@1t9Uj=nqm&90(7gpr!qK+2 zKwzKdh686EPg=uAlLtSXhRCVDnIx_2wKaRIC1+yInT%2Oo~AGpjZE7)uEMWa&4lEF z8FJ`c4@sJWzybx0hQ%$`go~M&h;)*Mu}TdU?i9}Vp-e~~CUxI3eFzT9Z`z&5O|{L7 z{`6CRDN%V1SsPC-DUNE2-Gv9P3o{}(Ac!g>js)OtWFnwu(O&iZ?|jb>)p|+wO;|qP z$!uERrzk7VsIj@GWoLoy+Nv;x7JBk)P0rxxX(OUp3w<9-JU5L@=bOU&P_b+G2B{1_ zmDD&Kp~|c83Gg}7@#ex6p{pmF|9vd1cfJjB@M=pdS);8hTCDrrc++{e1tLW~o)iPI zaX(UMFaGmVHCP9FJ6x=$)`hH|1#k?2gq#JdrptFv-IwHatYtfs#6BkSC@rK#Ap?f; z`Q^k19I1f(x%k8^p{&U;;qh`oOPh@+OVv*UvN_{Akj{mO`^Lz!hPX5J)8X3f%YBiT zz#*X_7IsF7`CNbbAiV({7}u>XvJ<<8L}r6MLdYz`4`XaC)G>;@k*2Qk zJT2RL`{zQJ81v_7+>pRlA#uoUainq%L-k$v+h=2wR528{L3Gu2&mZt z60a@;%#idQmy+s|GK41J22bEJYs3QSY~X{mLx1H%Z+x$1=+_q_xzT2eR!9uT!FdNB za3=9DTh&$h5K;~ zbk!=1bC?!1|JLj<72CW~KH6D2(se-HT%_tkKB7WwP?@09i7E1^l}Ty5SY+&DsNe0x z`fKsxC%)~NUjc*O6ZdX;ImR2;WP#DhW)8?x@5t+cfzNDW>x#3;9;cS*l7VMb5Vcdy)VLbTk_rF?y%d-MCd~CfH%x^ zrwR3B-v%&;yHWWv>@IDcFcD<}9d1R0q_$t*u$a9q-f)BM(Z&83Q8sWHWxX#_(1?M` zemtmLa7?u5KhLa)xmx$X4AxAjx>)K6NeD=tq0YpQUxV(pV~AQFyQhimNK<_DAhDx<&|rsrfcqT88!QAQVRs@R z;&MczdzEMLluBe{b6hY!lO!Vw?SMdTYq@0ua%^p9JLOKZ>{RvXEmVsff}o}c_{8*6 z#D^w28FP#l=GKzEM?n%6o!66gbV9Gred3(w)KP7g#+hE(7(LsGsnYl%xBX`i+fGje zUP%$lOnVPAe^swTs_!Zh&7|5+iJ)#Cn=Rku-@xXpRfid3%|874a(1C;7~>aG@N|1_ zMU<*La`@lLMDk*-0DW-pMPR!Vi3bI;@Hriv>I3E%h;igVJA6)7c?0u*f_ zp`W*ruDs(LQ^`8M2xH*mc9+(XIry6xsC%+?{?j9J$z_N?JIt@F_PQcu(7PLg^ciiG zhjpc40sIA%*GYhexxe(P%)ke88@N+iI;rkr+nt{{Z8eJ5g$>YaHVke+F8h@cG_xU* z4SJ_|SiRgF{(xY_wO4~Qi4~)jUEiM3;-|Q);B)@)jhh8O1U%C!V}Ou@%USw%S6?)`R+cIpb%zXR|x!%`mS6F5pZE%o&QJpsHp`U98UeiuYR=29)61SLCk z7V<%>buw^L z0Pz4DM=43`#l+1&ZS>o46QpJqp!Mk^iIfES+O)yKADFtO`|Q@V5$xisTsiB@JCiF& zAIF?rhey00Rk{9aM~|+Ov=O zvX+C{IDL1gDzpk^@ZN`Ku2(?1kHhUfJcT$%%iPi+Um-z08vQcH!QADEG`Z2CuMuzY z^TxotxlbjK+0Ryyy8zsr=v$CX3Qp3=^SufKdOV6v4;IF*Elw2ADg|x9psg8mWmArr@>I2u=xA-p& zlC1@vJ*B~4UvB=cZ@jHY`u7%b(j|&53`-@U_v_RYd>KZ)v!3(2t&Nl()3rGhnkTLnXhdO!}rKvh#I~3BHJ&AN#om45_8Mp+s zJyB;QR({yliJancgCS#Z-E_~zEwP;yo*}DC35UBo!jai+g?u9^IHf^LA(z zS5tABb;hR!gI>NbN1rp0K(FkH`gW^X7@&XX9=}tbdls5&3s{l6?_Q$ohr`Rr0MF6% zUksrEr$Onmaqi7qlmP8msQVHZJO`q97m7j^iBE9fQYibdzN18b!m?K^G8+P#JU17K zOQwB^Kf16~H}M%UbR;<-KEtT4{eBezgdQ1cDg z@VOVD9jrSsl^I%4zM@wWkfhq{N>PBT+ogVkKyzrqSmDBNJ(Dpgn&@l}_uj9YSe1jA zt%D0F3nfm&QpMGCS;wQzr4$dM+zwz3+!se^=miTIPWU&6?A=6zs-2SxA;zv#pXEtY1_#VO?X=XTrPXQ{5J89{C{Bdr@xin! zKD$2>e&jg?(ZJhq!kqHA{X;$ow5pD9pob>`Aya2;JexxKL@oTbZL>=5+xfis6b!J^7cxK5b^C> z&&+z*J!*-{?3+6dJSh=IYyQFJGrkXidC?U>x9ICvGiTs`ZQ6qY%2wqFid>|9qOXTP z49Z)rn;CdOBwunYTthAz!UcatjA_E}UP+&sASB?T1vqDct^ynnrIXv%F+n=gcgP<` zRoX`AAuji!T9+-LyMK8A4`pS*pf?z-H>VJq3U1M(^~xQ3tT{A6l0a+a(-(vIzP{il z=6o>uyx`IsKUXCJS!{o-v{tSuu-z@3LebGBJe_=jd!wi9x=N1Y+tvAFvQm0PpHWvy z?L@{yDvsbL=tXxuqp`xs^e7mO^F$pJ$;i6o-7&-PK8A21kH1S`{~;&*m}O?g6O7p* zNG=Aq13tkf*E=ya6#RDoYx~gb32{TPCLB91<%lP`OQLNr=m&DiYi$1Yx-a#K2ku-;*OUd{ji!C({43m!zaf`qU5Z%53O+1)EkQ^7;ZB_N!O)NAkG&aIdAUj%mComh zc`@W(IoA{h#6G>rzh2@PVx6vQH1D7fes({kOk#`3UJT;0AX5i2k{dVW_q~-voZjNNuORB+cNXcYsa-m5D^6oj?q|8!oPW*# zclBr!NJusytXM|A3PCq^(c*I(l2J{u|2y0NU^>mc$7!g?rZ=;4=b!u|Sr9+vIIJtU zt{i$mLUgiszXMtp#7r7*jy=lNKU(=8o=KbI@*+5meJ6)|fuC1!%Ta1CDOXAWpZ-7l z8R%Bc1)zl7I58;y|K!)Reu8o6r0i9j;S=W5=D)7Y;a4R8t$vuyjA2IQ2KQqA4}rg& A maxlen) { - maxlen = s[0]; - } - } - } - - // Set up our state, for later interleaved draw requests - this.set_state = function(x, y, rotation, turret, flags, sensor_state) { - this.x = x; - this.y = y; - this.rotation = rotation; - this.turret = turret; - if (flags & 1) { - this.fire = 5; - } - this.led = flags & 2; - this.dead = flags & 4; - this.sensor_state = sensor_state; - } - - this.draw_crater = function() { - if (!this.dead) { - return; - } - - var points = 7; - var angle = Math.PI / points; - - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - if (this.fire == 5) { - ctx.save(); - ctx.rotate(this.turret); - // one frame of cannon fire - this.draw_cannon(); - this.fire = 0; - ctx.restore(); - } - - ctx.lineWidth = 2; - ctx.strokeStyle = craterStroke; - ctx.fillStyle = craterFill; - ctx.beginPath(); - ctx.moveTo(12, 0); - for (i = 0; i < points; i += 1) { - ctx.rotate(angle); - ctx.lineTo(6, 0); - ctx.rotate(angle); - ctx.lineTo(12, 0); - } - ctx.closePath() - ctx.stroke(); - ctx.fill(); - - ctx.restore(); - } - - this.draw_sensors = function() { - if (this.dead) { - return; - } - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - ctx.lineWidth = 1; - for (i in this.sensors) { - var s = this.sensors[i]; - var adj = this.turret * s[3]; - - if (this.sensor_state & (1 << i)) { - // Sensor is triggered - ctx.strokeStyle = "#000"; - } else { - ctx.strokeStyle = sensorStroke; - } - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.arc(0, 0, s[0], s[1] + adj, s[2] + adj, false); - ctx.closePath(); - ctx.stroke(); - } - - ctx.restore(); - } - - this.draw_tank = function() { - if (this.dead) { - return; - } - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - ctx.fillStyle = color; - ctx.fillRect(-5, -4, 10, 8); - ctx.fillStyle = "#777"; - ctx.fillRect(-7, -9, 15, 5); - ctx.fillRect(-7, 4, 15, 5); - ctx.rotate(this.turret); - if (this.fire) { - this.draw_cannon(); - this.fire -= 1; - } else { - if (this.led) { - ctx.fillStyle = "#f00"; - } else { - ctx.fillStyle = "#000"; - } - ctx.fillRect(0, -1, 10, 2); - } - - ctx.restore(); - } - - this.draw_cannon = function() { - ctx.fillStyle = ("rgba(255,255,64," + this.fire/5 + ")"); - ctx.fillRect(0, -1, 45, 2); - } - - this.draw_wrap_sensors = function() { - var orig_x = this.x; - var orig_y = this.y; - for (x = this.x - width; x < width + maxlen; x += width) { - for (y = this.y - height; y < height + maxlen; y += height) { - if ((-maxlen < x) && (x < width + maxlen) && - (-maxlen < y) && (y < height + maxlen)) { - this.x = x; - this.y = y; - this.draw_sensors(); - } - } - } - this.x = orig_x; - this.y = orig_y; - } -} - -var loop_id; -var updateFunc = null; -function togglePlayback() { - if ($("#playing").prop("checked")) { - loop_id = setInterval(updateFunc, 66); - } else { - clearInterval(loop_id); - loop_id = null; - } - $("#pauselabel").toggleClass("ui-icon-play ui-icon-pause"); -} - -function start(id, game) { - var canvas = document.getElementById(id); - var ctx = canvas.getContext('2d'); - - canvas.width = game[0][0]; - canvas.height = game[0][1]; - // game[2] is tank descriptions - var turns = game[2]; - - // Set up tanks - var tanks = new Array(); - for (i in game[1]) { - var desc = game[1][i]; - tanks[i] = new Tank(ctx, game[0][0], game[0][1], desc[0], desc[1]); - } - - var frame = 0; - var lastframe = 0; - var fps = document.getElementById('fps'); - - function update_fps() { - fps.innerHTML = (frame - lastframe); - lastframe = frame; - } - - function drawFrame(idx) { - canvas.width = canvas.width; - turn = turns[idx]; - - // Update and draw craters first - for (i in turn) { - t = turn[i]; - if (!t) { - // old data, force-kill it - tanks[i].fire = 0; - tanks[i].dead = 5; - } else { - tanks[i].set_state(t[0], t[1], t[2], t[3], t[4], t[5]); - } - tanks[i].draw_crater(); - } - // Then sensors - for (i in turn) { - tanks[i].draw_wrap_sensors(); - } - // Then tanks - for (i in turn) { - tanks[i].draw_tank() - } - - document.getElementById('frameid').innerHTML = idx; - } - - function update() { - var idx = frame % (turns.length + 20); - var turn; - - frame += 1; - if (idx >= turns.length) { - return; - } - - drawFrame(idx); - - $('#seekslider').slider('value', idx); - } - - function seekToFrame(newidx) { - var idx = frame % (turns.length + 20); - if (idx !== newidx) { - frame = newidx; - drawFrame(newidx); - } - // make sure we're paused - if ($("#playing").prop("checked")) { - $("#playing").prop("checked", false); - togglePlayback(); - } - } - - updateFunc = update; - loop_id = setInterval(update, 66); - //loop_id = setInterval(update, 400); - if (fps) { - setInterval(update_fps, 1000); - } - - if (id === "battlefield") { - $("#game_box").append('

0

'); - $('#playing').button(); - var slider = $('#seekslider'); - slider.slider({ max: turns.length-1, slide: function(event, ui) { seekToFrame(ui.value); } }); - - var spacing = 100 / turns.length; - var deaths = []; - for (i in turns[0]) { - deaths.push(false); - } - var percent = 0; - for (var f = 0; f < turns.length; f++) { - var turn = turns[f]; - if (percent < (spacing * f)) { - percent = spacing * f; - } - for (var i = 0; i < turn.length; i++) { - if (deaths[i]) { continue; } - if (!turn[i] || (turn[i][4] & 4)) { - deaths[i] = true; - // http://stackoverflow.com/questions/8648963/add-tick-marks-to-jquery-slider - $('').css('left', percent + '%').css('background-color', game[1][i][0]).appendTo(slider); - percent++; - break; - } - } - } - } -} - diff --git a/docs/_site/history.html b/docs/_site/history.html deleted file mode 100644 index 58284ab..0000000 --- a/docs/_site/history.html +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - by - - - -

History

- -

This is a port of the “Tanks” program written by Paul Ferrell -pflarr@clanspum.net in 2009-2010. Paul created the entire game based -off a brief description I provided him of -Crobots -and a vague desire to -“make something fun for high school kids to learn some programming.” We -ran Paul’s Tanks as part of a 100-attendee computer security contest in -February of 2010 and by all accounts it was a huge success. It even -made the nightly news.

- -

Paul’s version was written in Python and provided a custom language -called “Bullet”, which looked like this:

- -
>addsensor(50, 0, 5, 1);        # 0
->addsensor(100, 90, 150, 1);    # 1
->addsensor(100, 270, 150, 1);   # 2
->addsensor(100, 0, 359, 0);     # 3
-
-# Default movement if nothing is detected
-            : move(70, 70) . turretccw();
-random(2, 3): move(40, 70) . turretccw();
-random(1, 3): move(70, 40) . turretccw();
-
-# We found something!!
-sense(3): move(0, 0);
-sense(1): turretcw();
-sense(2): turretccw();
-sense(0): fire();
-
-
- - - - - - -
"Chashtank" cleans up.
- - -
- -

Nick Moffitt played with this original version and convinced me (Neale) -that something like Forth would be a better language. I added some code -to accept a scaled-down version of PostScript. The IRC channel we -frequent collectively agreed to give this new language the derisive name -“Forf”, which should ideally be followed by punching someone after it is -spoken aloud. I wrote a Python implementation of Forf, which was slow, -and then Adam Glasgall wrote a C implementation, which was quick.

- -

I decided to take Tanks to Def Con in July 2010, and just for bragging -rights, to have it run on an Asus WL-500gU. This is a $50 device with a -240 MHz MIPS CPU, 16MB RAM, and a 4MB flash disk, along with an -802.11b/g radio, 4-port 10/100 switch, and an additional 10/100 “uplink” -port; it’s sold as a home wireless router. I had originally intended to -run it off a lantern battery just for fun, but eventually thought better -of it: doing so would be wasteful for no good reason.

- -

Aaron McPhall amcphall@mcphall.org, my summer intern at the time, got -OpenWRT and Python onto the box and benchmarked it at about 60 seconds -for a 16-tank game, after he had profiled the code and optimized a lot -of the math. That wasn’t bad, it meant we could run a reasonably-sized -game at one turn per minute, which we knew from past experience was -about the right rate. But it required a USB thumb drive to hold Python, -and when we used the Python Forf implementation, the run-time shot up to -several minutes. I began this C port while Adam Glasgall, another fool -on the previously-mentioned IRC channel, started work on a C version of -a Forf interpreter.

- -

This C version with Forf runs about 6 times faster than the Python -version with Bullet, on the WL-500gU. A 1GHz Intel Atom runs a 16-tank -game in about 0.2 seconds.

- -

What’s so great about Forf?

- -

Nothing’s great about Forf. It’s a crummy language that only does -integer math. For this application it’s a good choice, for the -following reasons:

- -
    -
  • No library dependencies, not even malloc
  • -
  • Runs in fixed size memory
  • -
  • Not Turing-complete, I think (impossible to make endless loops)
  • -
  • Lends itself to genetic algorithms
  • -
- - - - - diff --git a/docs/_site/index.html b/docs/_site/index.html deleted file mode 100644 index 5852315..0000000 --- a/docs/_site/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - by - - - -

Tanks

- - - - -
"Ant Lion" nails "Rabbit With Gun".
- - -
- -

Dirtbags Tanks is a game in which you pit your coding abilities -against other hackers. You write a program for your tank, set it out -on the battlefield, and watch how your program fares against tanks -written by other players. Dirtbags Tanks is frequently a component of -Dirtbags Capture The Flag.

- -

Each tank has a turret-mounted laser, two treads, up to ten sensors, -and a diagnostic LED. Sensors are used to detect when other tanks are -inside a given arc. In the examples on this page, “triggered” sensors -turn black. Most tanks will take some action if a sensor is -triggered, such as changing speed of the treads, turning the turret, -or firing.

- -

Tanks are programmed in Forf, a stack-based language similar to -PostScript.

- -

Other Versions

- -

Everybody loves tanks! -If you’ve made a port or done something fun with it, -please let me know and I’ll link it here!

- -
    -
  • Class Lab at New Mexico Tech, by Russell White
  • -
- -

Author

- -

Neale Pickett neale@woozle.org

- - - - - diff --git a/docs/_site/running.html b/docs/_site/running.html deleted file mode 100644 index 67a9e6d..0000000 --- a/docs/_site/running.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - by - - - -

Running Tanks

- -

Unfortunately, it’s kind of a mess right now. -I know there are a few forks of this code, -and I would love it if someone proposed a merge to clearly illustrate how to run tanks.

- -

When I spin up a new tanks game, -typically I run something like:

- -
while sleep 60; do ./round.sh */; done
-
-
- -

This assumes all your tanks directories are in the same place as round.sh.

- -

Included programs

- -

I tried to stick with the Unix philosophy of one program per task. I -also tried to avoid doing any string processing in C. The result is a -hodgepodge of C, Bourne shell, and awk, but at least each piece is -fairly simple to audit.

- -

round.sh tank1 tank2 …

- -

Runs a single round, awards points with rank.awk, and creates a new -summary.html with summary.awk. This is the main interface that you want -to run from cron or whatever.

- -

forftanks tank1 tank2 …

- -

A program to run a round of tanks and output a JSON description of the -game. This is what tanks.js uses to render a game graphically. -The object printed contains:

- -
[[game-width, game-height],
- [[tank1-color, 
-  [[sensor1range, sensor1angle, sensor1width, sensor1turret],
-   ...]],
-  ...],
- [[
-  [tank1x, tank1y, tank1angle, tank1sensangle, 
-   tank1flags, tank1sensors],
-  ...],
- ...]]
-
-
- -

If file descriptor 3 is open for writes, it also outputs the results of -the round to fd3.

- -

rank.awk

- -

Processes the fd3 output of forftanks to award points and output an -HTML results table.

- -

summary.awk tank1 tank2

- -

Creates summary.html, linking to all rounds and showing overall -standing.

- -

designer.cgi

- -

Accepts form input and writes a tank.

- - - - - - diff --git a/docs/_site/standie.svg b/docs/_site/standie.svg deleted file mode 100644 index 76e6875..0000000 --- a/docs/_site/standie.svg +++ /dev/null @@ -1,260 +0,0 @@ - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - dirtbags - - - - - - - - - - - - - - diff --git a/docs/_site/thanks.html b/docs/_site/thanks.html deleted file mode 100644 index 53d1beb..0000000 --- a/docs/_site/thanks.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - by - - - -

thanks

- -
    -
  • Tom Poindexter: Inspiration (Author of CRobots)
  • -
  • Paul Ferrell: Initial implementation
  • -
  • Aaron McPhall: Math optimizations
  • -
  • Nick Moffitt: Suggestion to use FORTH-like language
  • -
  • Anna Glasgall: C Forf prototype
  • -
  • Adam Thomas: Various patches
  • -
  • Various Australians: Creation of some mind-blowing tanks
  • -
  • Alyssa Milburn: JS Tanks, Tank Debugger, many more other helpful contributions
  • -
- - - - - diff --git a/docs/_site/token.svg b/docs/_site/token.svg deleted file mode 100644 index 4cb6bb4..0000000 --- a/docs/_site/token.svg +++ /dev/null @@ -1,1897 +0,0 @@ - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - - - - - - - - - dirtbags! - - - - - - - - - - - - - essid: tankshttp://192.168.1.1/password: - - - diff --git a/docs/assets/css/dirtbags.css b/docs/assets/css/dirtbags.css deleted file mode 100644 index 6a86e06..0000000 --- a/docs/assets/css/dirtbags.css +++ /dev/null @@ -1,151 +0,0 @@ -/**** document ****/ - -html { - background: #eed url(/assets/images/grunge.png) repeat-x; -} - -body { - font-family: sans-serif; - color: #112; - padding: 10px; - max-width: 700px; -} - -/**** heading ****/ - -#title { - text-transform: lowercase; - font-size: 1.6em; - padding: 3px; - margin: 0 0 1em 2em; -} - -#title:before { - color: #999; - letter-spacing: -0.1em; - content: "Dirtbags: "; -} - -/*** left side bar ***/ - -nav h2 { - display: none; -} - -nav ul { - list-style: none; - text-align: center; -} - -nav li { - display: inline; -} - -nav li a { - text-transform: lowercase; - font-size: 0.9em; -} - -nav li + li:before { - content: " | "; -} - - -/**** body ****/ - -a img { - border: 0px; -} - -a { - text-decoration: none; - color: #2a4; - font-weight: bold; -} - -a:hover { - color: #ddc; - background: #2a4; -} - - -h1, h2, h3 { - color: #464; - letter-spacing: -0.05em; -} - -.readme { - background-color: #ccc; - margin: 1em; -} - -pre { - background-color: #ccc; - border: solid #888 2px; - padding: 0.25em; -} - - -th { - vertical-align: top; - text-align: center; -} -td { - vertical-align: top; - text-align: right; -} - -p { - line-height: 1.4em; - margin-bottom: 20px; -} - -hr { - border: 1px solid #444; -} - -dt { - white-space: pre; - background-color: #333; - padding: 5px; - border: 2px solid green; - border-bottom: none; - font-weight: bold; -} - -dd { - border: 2px solid green; - margin: 0px; - padding: 5px; - background-color: #282828; -} - - -/**** special cases ****/ - -.wide { - max-width: inherit; -} - -.figure { - margin: 0.5em 1em; - float: right; - font-size: small; - text-align: center; -} - -.scoreboard { - background: #222; -} - -.scoreboard td { - height: 400px; -} - -#battlefield { - border: 2px solid green; -} - -.solved { - text-decoration: line-through; -} diff --git a/docs/assets/images/grunge.png b/docs/assets/images/grunge.png deleted file mode 100644 index 9a8c41a59bdff7795373467cb677a9a49cf8b04e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6761 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 A maxlen) { - maxlen = s[0]; - } - } - } - - // Set up our state, for later interleaved draw requests - this.set_state = function(x, y, rotation, turret, flags, sensor_state) { - this.x = x; - this.y = y; - this.rotation = rotation; - this.turret = turret; - if (flags & 1) { - this.fire = 5; - } - this.led = flags & 2; - this.dead = flags & 4; - this.sensor_state = sensor_state; - } - - this.draw_crater = function() { - if (!this.dead) { - return; - } - - var points = 7; - var angle = Math.PI / points; - - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - if (this.fire == 5) { - ctx.save(); - ctx.rotate(this.turret); - // one frame of cannon fire - this.draw_cannon(); - this.fire = 0; - ctx.restore(); - } - - ctx.lineWidth = 2; - ctx.strokeStyle = craterStroke; - ctx.fillStyle = craterFill; - ctx.beginPath(); - ctx.moveTo(12, 0); - for (i = 0; i < points; i += 1) { - ctx.rotate(angle); - ctx.lineTo(6, 0); - ctx.rotate(angle); - ctx.lineTo(12, 0); - } - ctx.closePath() - ctx.stroke(); - ctx.fill(); - - ctx.restore(); - } - - this.draw_sensors = function() { - if (this.dead) { - return; - } - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - ctx.lineWidth = 1; - for (i in this.sensors) { - var s = this.sensors[i]; - var adj = this.turret * s[3]; - - if (this.sensor_state & (1 << i)) { - // Sensor is triggered - ctx.strokeStyle = "#000"; - } else { - ctx.strokeStyle = sensorStroke; - } - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.arc(0, 0, s[0], s[1] + adj, s[2] + adj, false); - ctx.closePath(); - ctx.stroke(); - } - - ctx.restore(); - } - - this.draw_tank = function() { - if (this.dead) { - return; - } - ctx.save(); - ctx.translate(this.x, this.y); - ctx.rotate(this.rotation); - - ctx.fillStyle = color; - ctx.fillRect(-5, -4, 10, 8); - ctx.fillStyle = "#777"; - ctx.fillRect(-7, -9, 15, 5); - ctx.fillRect(-7, 4, 15, 5); - ctx.rotate(this.turret); - if (this.fire) { - this.draw_cannon(); - this.fire -= 1; - } else { - if (this.led) { - ctx.fillStyle = "#f00"; - } else { - ctx.fillStyle = "#000"; - } - ctx.fillRect(0, -1, 10, 2); - } - - ctx.restore(); - } - - this.draw_cannon = function() { - ctx.fillStyle = ("rgba(255,255,64," + this.fire/5 + ")"); - ctx.fillRect(0, -1, 45, 2); - } - - this.draw_wrap_sensors = function() { - var orig_x = this.x; - var orig_y = this.y; - for (x = this.x - width; x < width + maxlen; x += width) { - for (y = this.y - height; y < height + maxlen; y += height) { - if ((-maxlen < x) && (x < width + maxlen) && - (-maxlen < y) && (y < height + maxlen)) { - this.x = x; - this.y = y; - this.draw_sensors(); - } - } - } - this.x = orig_x; - this.y = orig_y; - } -} - -var loop_id; -var updateFunc = null; -function togglePlayback() { - if ($("#playing").prop("checked")) { - loop_id = setInterval(updateFunc, 66); - } else { - clearInterval(loop_id); - loop_id = null; - } - $("#pauselabel").toggleClass("ui-icon-play ui-icon-pause"); -} - -function start(id, game) { - var canvas = document.getElementById(id); - var ctx = canvas.getContext('2d'); - - canvas.width = game[0][0]; - canvas.height = game[0][1]; - // game[2] is tank descriptions - var turns = game[2]; - - // Set up tanks - var tanks = new Array(); - for (i in game[1]) { - var desc = game[1][i]; - tanks[i] = new Tank(ctx, game[0][0], game[0][1], desc[0], desc[1]); - } - - var frame = 0; - var lastframe = 0; - var fps = document.getElementById('fps'); - - function update_fps() { - fps.innerHTML = (frame - lastframe); - lastframe = frame; - } - - function drawFrame(idx) { - canvas.width = canvas.width; - turn = turns[idx]; - - // Update and draw craters first - for (i in turn) { - t = turn[i]; - if (!t) { - // old data, force-kill it - tanks[i].fire = 0; - tanks[i].dead = 5; - } else { - tanks[i].set_state(t[0], t[1], t[2], t[3], t[4], t[5]); - } - tanks[i].draw_crater(); - } - // Then sensors - for (i in turn) { - tanks[i].draw_wrap_sensors(); - } - // Then tanks - for (i in turn) { - tanks[i].draw_tank() - } - - document.getElementById('frameid').innerHTML = idx; - } - - function update() { - var idx = frame % (turns.length + 20); - var turn; - - frame += 1; - if (idx >= turns.length) { - return; - } - - drawFrame(idx); - - $('#seekslider').slider('value', idx); - } - - function seekToFrame(newidx) { - var idx = frame % (turns.length + 20); - if (idx !== newidx) { - frame = newidx; - drawFrame(newidx); - } - // make sure we're paused - if ($("#playing").prop("checked")) { - $("#playing").prop("checked", false); - togglePlayback(); - } - } - - updateFunc = update; - loop_id = setInterval(update, 66); - //loop_id = setInterval(update, 400); - if (fps) { - setInterval(update_fps, 1000); - } - - if (id === "battlefield") { - $("#game_box").append('

0

'); - $('#playing').button(); - var slider = $('#seekslider'); - slider.slider({ max: turns.length-1, slide: function(event, ui) { seekToFrame(ui.value); } }); - - var spacing = 100 / turns.length; - var deaths = []; - for (i in turns[0]) { - deaths.push(false); - } - var percent = 0; - for (var f = 0; f < turns.length; f++) { - var turn = turns[f]; - if (percent < (spacing * f)) { - percent = spacing * f; - } - for (var i = 0; i < turn.length; i++) { - if (deaths[i]) { continue; } - if (!turn[i] || (turn[i][4] & 4)) { - deaths[i] = true; - // http://stackoverflow.com/questions/8648963/add-tick-marks-to-jquery-slider - $('').css('left', percent + '%').css('background-color', game[1][i][0]).appendTo(slider); - percent++; - break; - } - } - } - } -} - diff --git a/docs/forf.html.m4 b/docs/forf.html.m4 deleted file mode 100644 index 65a4de5..0000000 --- a/docs/forf.html.m4 +++ /dev/null @@ -1,13 +0,0 @@ - - - - Forf Manual - - - - -syscmd(markdown forf.txt) -include(nav.html.inc) - - - diff --git a/docs/history.md b/docs/history.md index d94efc3..3873dbf 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,9 +1,4 @@ ---- -title: History -scripts: - - assets/js/tanks.js - - assets/js/figures.js ---- +# History This is a port of the "Tanks" program written by Paul Ferrell in 2009-2010. Paul created the entire game based @@ -34,18 +29,6 @@ called "Bullet", which looked like this: sense(2): turretccw(); sense(0): fire(); - - - - - -
"Chashtank" cleans up.
- - -
- Nick Moffitt played with this original version and convinced me (Neale) that something like Forth would be a better language. I added some code to accept a scaled-down version of PostScript. The IRC channel we diff --git a/docs/intro.html.m4 b/docs/intro.html.m4 deleted file mode 100644 index 6d31e1f..0000000 --- a/docs/intro.html.m4 +++ /dev/null @@ -1,147 +0,0 @@ - - - - Tanks Introduction - - - - - - -

Tanks Introduction

- - - - - - -
"ChashTank" dominates this short round.
- - -
- -

- Tanks is a game in which you pit your coding abilities against - other hackers. You write a program for your tank, set it out on - the battlefield, and watch how it fares against other tanks while - running your program. -

- -

- Each tank has a turret-mounted laser, two treads, up to ten - sensors, and a diagnostic LED. Sensors are used to detect when - other tanks are inside a given arc. In the examples on this page, - "triggered" sensors turn black. Most tanks will take some action - if a sensor is triggered, such as changing speed of the treads, - turning the turret, or firing. -

- -

- Tanks are programmed in Forf, a stack-based language similar to - PostScript. Please read the Forf manual - to learn more about forf, and the Tanks - procedure reference for a description of Tanks extensions. -

- -

Quick Start for the Impatient

- - - - - - -
"Crashmaster" pwns the lame default tank provided in this - section.
- - -
- -

- To get started, head over to the Tank - Debugger and enter the following example tank. This tank will - move around, turn the turret, and fire if there's something in - front of it. -

- -
-Sensor 0: 50 0 7 ☑
-Sensor 1: 30 0 90 ☐
-
-get-turret 12 + set-turret!         ( Rotate turret )
-37 40 set-speed!                    ( Go in circles )
-0 sensor? { fire! } if              ( Fire if turret sensor triggered )
-1 sensor? { -50 50 set-speed! } if  ( Turn if collision sensor triggered )
-    
- -

- Obviously, this tank could be improved. Studying the examples on - this page should give you ideas about how to make a better tank. - Don't forget the Forf manual and the - Tank procedure reference. -

- -

Tank Specifications

- - - - - - -
"Ant Lion" nails "Rabbit With Gun".
- - -
- -

- Your PF-255 autonomous tank is built to the exacting - specifications sent to our factory in New Khavistan. All - distances are in meters, angles in degrees. -

- -
-
Tank size
-
- The targettable area of the tank—the part which can be hit by a - cannon—is a circle about 7½ meters in radius. -
- -
Speed
-
- Each tread can have a speed between -100 and 100. This is in - percentage of total speed for that tread, where total speed is - roughly 7 meters per turn. -
- -
Sensors
-
- Each sensor has a maximum range of 100 meters. Of course, you - don't have to use the full range. Sensors may be attached to - the turret (they turn along with the turret), or left fixed to - the tank. -
- -
Turret
-
- Turret angle can be set between -359° and 359°, with 0° directly - in front of the tank. Be aware that it takes time for the - turret to swing around: the turret can swing about 45° per turn. -
- -
Cannon range and recharging
-
- When the cannon is fired, it obliterates everything for 50 - meters in front of it. It takes around 20 turns for your cannon - to recharge after it's been fired, so only shoot when you feel - like you're going to hit something. -
-
- - Good luck blowing everybody up! -include(nav.html.inc) - diff --git a/docs/intro.md b/docs/intro.md new file mode 100644 index 0000000..add5033 --- /dev/null +++ b/docs/intro.md @@ -0,0 +1,72 @@ +# Tanks Introduction + +Tanks is a game in which you pit your coding abilities against +other hackers. You write a program for your tank, set it out on +the battlefield, and watch how it fares against other tanks while +running your program. + +Each tank has a turret-mounted laser, two treads, up to ten +sensors, and a diagnostic LED. Sensors are used to detect when +other tanks are inside a given arc. In the examples on this page, +"triggered" sensors turn black. Most tanks will take some action +if a sensor is triggered, such as changing speed of the treads, +turning the turret, or firing. + +Tanks are programmed in Forf, a stack-based language similar to +PostScript. Please read the [Forf manual](forf.md) to learn more +about forf, and the [Tanks procedure reference](procs.html) for a +description of Tanks extensions. + +## Quick Start for the Impatient + +To get started, head over to the designer for your game, +and use the following example tank. This tank will +move around, turn the turret, and fire if there's something in +front of it. + + Sensor 0: 50 0 7 ☑ + Sensor 1: 30 0 90 ☐ + + get-turret 12 + set-turret! ( Rotate turret ) + 37 40 set-speed! ( Go in circles ) + 0 sensor? { fire! } if ( Fire if turret sensor triggered ) + 1 sensor? { -50 50 set-speed! } if ( Turn if collision sensor triggered ) + +Obviously, this tank could be improved. +Watch other tanks in your game to get ideas about how to improve yours. +Don't forget the [Forf manual](forf.md) and the +[Tank procedure reference](procs.html). + +## Tank Specifications + +Your PF-255 autonomous tank is built to the exacting +specifications sent to our factory in New Khavistan. All +distances are in meters, angles in degrees. + + +Tank size +: The targettable area of the tank—the part which can be hit by a cannon—is a circle about 7½ meters in radius. + +Speed +: Each tread can have a speed between -100 and 100. This is in + percentage of total speed for that tread, where total speed is + roughly 7 meters per turn. + +Sensors +: Each sensor has a maximum range of 100 meters. Of course, you + don't have to use the full range. Sensors may be attached to + the turret (they turn along with the turret), or left fixed to + the tank. + +Turret +: Turret angle can be set between -359° and 359°, with 0° directly + in front of the tank. Be aware that it takes time for the + turret to swing around: the turret can swing about 45° per turn. + +Cannon range and recharging +: When the cannon is fired, it obliterates everything for 50 + meters in front of it. It takes around 20 turns for your cannon + to recharge after it's been fired, so only shoot when you feel + like you're going to hit something. + +Good luck blowing everybody up! diff --git a/docs/nav.html.inc b/docs/nav.html.inc deleted file mode 100644 index b2ea44f..0000000 --- a/docs/nav.html.inc +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/docs/procs.html.m4 b/docs/procs.html.m4 deleted file mode 100644 index 2510df0..0000000 --- a/docs/procs.html.m4 +++ /dev/null @@ -1,74 +0,0 @@ - - - - Tanks Procedure Reference - - - - -

Tanks Procedure Reference

- -

- Each tank's program is run once per turn. The data and command - stacks are reset at the beginning of each turn, but memory is not, - so you can carry data over in memory registers if you want. See - the Forf manual for more information about - the base language. -

- -

- For tank specifications (sensor range, maximum speeds, etc.), see - the introduction. -

- - -

Limits

- -

- Forf Tanks has a data stack size of 200, and a command stack size - of 500. This means your program cannot have more than 200 data - items, or 500 instructions, including 2 instructions for each - substack. -

- -

- Forf Tanks provides 10 memory registers (0-9) which persist across - invocations of your tank's program. -

- - -

Additional Procedures

- -
-
fire-ready?
-
Returns 1 if the tank can fire, 0 if not.
- -
fire!
-
Fires the cannon.
- -
l r set-speed!
-
Sets the speed of the left and right treads (range: -100 to - 100).
- -
get-turret
-
Returns the current angle of the turret.
- -
a set-turret!
-
Set the turret to a degrees.
- -
n sensor?
-
Returns 1 if sensor n is triggered, 0 if not.
- -
s set-led!
-
Turns off the LED if s is 0, on for any other value.
- -
n random
-
Returns a random number in the range [0, n). That is, between - 0 and n-1, inclusive.
-
- -include(nav.html.inc) - - - - diff --git a/docs/procs.md b/docs/procs.md new file mode 100644 index 0000000..c003cb5 --- /dev/null +++ b/docs/procs.md @@ -0,0 +1,47 @@ +# Tanks Procedure Reference + +Each tank's program is run once per turn. The data and command +stacks are reset at the beginning of each turn, but memory is not, +so you can carry data over in memory registers if you want. See +the [Forf manual](forf.md) for more information about +the base language. + +For tank specifications (sensor range, maximum speeds, etc.), see +the [introduction](intro.html). + +## Limits + +Forf Tanks has a data stack size of 200, and a command stack size +of 500. This means your program cannot have more than 200 data +items, or 500 instructions, including 2 instructions for each +substack. + +Forf Tanks provides 10 memory registers (0-9) which persist across +invocations of your tank's program. + + +## Additional Procedures + +fire-ready? +: Returns 1 if the tank can fire, 0 if not. + +fire! +: Fires the cannon. + +l r set-speed! +: Sets the speed of the left and right treads (range: -100 to 100). + +get-turret +: Returns the current angle of the turret, in degrees. + +a set-turret! +: Begin moving the turret to a degrees. + +n sensor? +: Returns 1 if sensor n is triggered, 0 if not. + +s set-led! +: Turns off the LED if s is 0, on for any other value. + +n random +: Returns a random number in the range [0, n). That is, between 0 and n-1, inclusive. diff --git a/docs/running.md b/docs/running.md deleted file mode 100644 index 66dd857..0000000 --- a/docs/running.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Running Tanks ---- - -Unfortunately, it's kind of a mess right now. -I know there are a few forks of this code, -and I would love it if someone proposed a merge to clearly illustrate how to run tanks. - -When I spin up a new tanks game, -typically I run something like: - - while sleep 60; do ./run-tanks */; done - -This assumes all your tanks directories are in the same place as `run-tanks`. - - - -Included programs ------------------ - -I tried to stick with the Unix philosophy of one program per task. I -also tried to avoid doing any string processing in C. The result is a -hodgepodge of C, Bourne shell, and awk, but at least each piece is -fairly simple to audit. - - -### run-tanks tank1 tank2 ... - -Runs a single round, awards points with rank.awk, and creates a new -summary.html with summary.awk. This is the main interface that you want -to run from cron or whatever. - - -### forftanks tank1 tank2 ... - -A program to run a round of tanks and output a JSON description of the -game. This is what tanks.js uses to render a game graphically. -The object printed contains: - - [[game-width, game-height], - [[tank1-color, - [[sensor1range, sensor1angle, sensor1width, sensor1turret], - ...]], - ...], - [[ - [tank1x, tank1y, tank1angle, tank1sensangle, - tank1flags, tank1sensors], - ...], - ...]] - -If file descriptor 3 is open for writes, it also outputs the results of -the round to fd3. - - -### rank.awk - -Processes the fd3 output of forftanks to award points and output an -HTML results table. - - -### summary.awk tank1 tank2 - -Creates summary.html, linking to all rounds and showing overall -standing. - - -### designer.cgi - -Accepts form input and writes a tank. - - - -