about summary refs log tree commit diff stats
path: root/subx/apps/handle
Commit message (Expand)AuthorAgeFilesLines
* Merge branch 'master' into surveyKartik Agaram2019-07-031-0/+0
|\
| * 5219Kartik Agaram2019-05-221-0/+0
| * 5218Kartik Agaram2019-05-221-0/+0
| * 5217Kartik Agaram2019-05-221-0/+0
* | some primitives for emitting tracesKartik Agaram2019-07-011-0/+0
* | .Kartik Agaram2019-07-011-0/+0
* | unsigned comparison for addresses in more placesKartik Agaram2019-07-011-0/+0
* | .Kartik Agaram2019-06-281-0/+0
* | .Kartik Agaram2019-06-081-0/+0
* | Fix stale `initialize-trace-stream`Kartik Agaram2019-06-081-0/+0
* | .Kartik Agaram2019-06-081-0/+0
* | start fleshing out trace support some moreKartik Agaram2019-06-051-0/+0
* | .Kartik Agaram2019-05-271-0/+0
* | new primitive: check-array-equalKartik Agaram2019-05-261-0/+0
* | new primitive: parse-array-of-intsKartik Agaram2019-05-251-0/+0
* | .Kartik Agaram2019-05-251-0/+0
* | new primitive: array-equal?Kartik Agaram2019-05-251-0/+0
* | new primitive for tests: check-string-equalKartik Agaram2019-05-251-0/+0
|/
* 5189Kartik Agaram2019-05-181-0/+0
* 5180Kartik Agaram2019-05-161-0/+0
* complete the skeleton of dquotes.subxKartik Agaram2019-05-151-0/+0
* Merge branch 'dquotes' into dquotes-1Kartik Agaram2019-05-131-0/+0
|\
| * start using the new carry flagKartik Agaram2019-05-131-0/+0
| * 5156 - error-checking on writes to fileKartik Agaram2019-05-111-0/+0
| * 5154Kartik Agaram2019-05-111-0/+0
| * 5153Kartik Agaram2019-05-111-0/+0
* | Merge branch 'master' into dquotes-1Kartik Agaram2019-05-101-0/+0
|\|
| * 5151 - use mmap everywhere we need a heapKartik Agaram2019-05-101-0/+0
| * 5145Kartik Agaram2019-05-041-0/+0
| * 5135Kartik Agaram2019-05-041-0/+0
* | new primitives: append-byte, append-byte-hexKartik Agaram2019-05-021-0/+0
* | standardize function namesKartik Agaram2019-05-021-0/+0
|/
* 5118 - convert int to stringKartik Agaram2019-04-231-0/+0
* 5090Kartik Agaram2019-04-131-0/+0
* 5074Kartik Agaram2019-04-101-0/+0
* 5060Kartik Agaram2019-04-061-0/+0
* 5059Kartik Agaram2019-04-051-0/+0
* 5056Kartik Agaram2019-04-051-0/+0
* 5053Kartik Agaram2019-04-031-0/+0
* 5027Kartik Agaram2019-03-271-0/+0
* 4999Kartik Agaram2019-03-101-0/+0
* 4996 - back on pack.subxKartik Agaram2019-03-081-0/+0
* 4988Kartik Agaram2019-02-251-0/+0
* 4981 - no, go back to 3 phasesKartik Agaram2019-02-181-0/+0
* 4968Kartik Agaram2019-02-141-0/+0
* 4965Kartik Agaram2019-02-141-0/+0
* 4961Kartik Agaram2019-02-141-0/+0
* 4955Kartik Agaram2019-02-101-0/+0
* 4954Kartik Agaram2019-02-101-0/+0
* 4952Kartik Agaram2019-02-051-0/+0
/a> 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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - chessboard.mu</title>
<meta name="Generator" content="Vim/7.4">
<meta name="plugin-version" content="vim7.4_v2">
<meta name="syntax" content="none">
<meta name="settings" content="use_css,pre_wrap,no_foldcolumn,expand_tabs,prevent_copy=">
<meta name="colorscheme" content="minimal">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #eeeeee; background-color: #080808; }
body { font-size: 12pt; font-family: monospace; color: #eeeeee; background-color: #080808; }
* { font-size: 12pt; font-size: 1em; }
.muRecipe { color: #ff8700; }
.muData { color: #ffff00; }
.Special { color: #c00000; }
.muScenario { color: #00af00; }
.Delimiter { color: #800080; }
.Comment { color: #9090ff; }
.Constant { color: #00a0a0; }
.SalientComment { color: #00ffff; }
.CommentedCode { color: #6c6c6c; }
.muControl { color: #c0a020; }
-->
</style>

<script type='text/javascript'>
<!--

-->
</script>
</head>
<body>
<pre id='vimCodeElement'>
<span class="Comment"># Chessboard program: you type in moves in algebraic notation, and it'll</span>
<span class="Comment"># display the position after each move.</span>

<span class="muRecipe">def</span> main [
  open-console  <span class="Comment"># take control of screen, keyboard and mouse</span>

  <span class="Comment"># The chessboard function takes keyboard and screen objects as 'ingredients'.</span>
  <span class="Comment">#</span>
  <span class="Comment"># In mu it is good form (though not required) to explicitly show the</span>
  <span class="Comment"># hardware you rely on.</span>
  <span class="Comment">#</span>
  <span class="Comment"># Here the console and screen are both 0, which usually indicates real</span>
  <span class="Comment"># hardware rather than a fake for testing as you'll see below.</span>
  chessboard <span class="Constant">0/screen</span>, <span class="Constant">0/console</span>

  close-console  <span class="Comment"># clean up screen, keyboard and mouse</span>
]

<span class="SalientComment">## But enough about mu. Here's what it looks like to run the chessboard program.</span>

<span class="muScenario">scenario</span> print-board-and-read-move [
  trace-until <span class="Constant">100/app</span>
  <span class="Comment"># we'll make the screen really wide because the program currently prints out a long line</span>
  assume-screen <span class="Constant">120/width</span>, <span class="Constant">20/height</span>
  <span class="Comment"># initialize keyboard to type in a move</span>
  assume-console [
    type <span class="Constant">[a2-a4</span>
<span class="Constant">]</span>
  ]
  run [
    <span class="Constant">local-scope</span>
    screen:address:screen, console:address:console<span class="Special"> &lt;- </span>chessboard screen:address:screen, console:address:console
    <span class="Comment"># icon for the cursor</span>
    cursor-icon:character<span class="Special"> &lt;- </span>copy <span class="Constant">9251/␣</span>
    screen<span class="Special"> &lt;- </span>print screen, cursor-icon
  ]
  screen-should-contain [
  <span class="Comment">#            1         2         3         4         5         6         7         8         9         10        11</span>
  <span class="Comment">#  012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789</span>
   <span class="Constant"> .Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.         .</span>
   <span class="Constant"> .                                                                                                                        .</span>
   <span class="Constant"> .8 | r n b q k b n r                                                                                                     .</span>
   <span class="Constant"> .7 | p p p p p p p p                                                                                                     .</span>
   <span class="Constant"> .6 |                                                                                                                     .</span>
   <span class="Constant"> .5 |                                                                                                                     .</span>
   <span class="Constant"> .4 | P                                                                                                                   .</span>
   <span class="Constant"> .3 |                                                                                                                     .</span>
   <span class="Constant"> .2 |   P P P P P P P                                                                                                     .</span>
   <span class="Constant"> .1 | R N B Q K B N R                                                                                                     .</span>
   <span class="Constant"> .  +----------------                                                                                                     .</span>
   <span class="Constant"> .    a b c d e f g h                                                                                                     .</span>
   <span class="Constant"> .                                                                                                                        .</span>
   <span class="Constant"> .Type in your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.                               .</span>
   <span class="Constant"> .                                                                                                                        .</span>
   <span class="Constant"> .Hit 'q' to exit.                                                                                                        .</span>
   <span class="Constant"> .                                                                                                                        .</span>
   <span class="Constant"> .move: ␣                                                                                                                 .</span>
   <span class="Constant"> .                                                                                                                        .</span>
   <span class="Constant"> .                                                                                                                        .</span>
  ]
]

<span class="SalientComment">## Here's how 'chessboard' is implemented.</span>

<span class="muRecipe">def</span> chessboard screen:address:screen, console:address:console<span class="muRecipe"> -&gt; </span>screen:address:screen, console:address:console [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position
  <span class="Comment"># hook up stdin</span>
  stdin-in:address:source:character, stdin-out:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
  start-running send-keys-to-channel, console, stdin-out, screen
  <span class="Comment"># buffer lines in stdin</span>
  buffered-stdin-in:address:source:character, buffered-stdin-out:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">10/capacity</span>
  start-running buffer-lines, stdin-in, buffered-stdin-out
  <span class="Delimiter">{</span>
    print screen, <span class="Constant">[Stupid text-mode chessboard. White pieces in uppercase; black pieces in lowercase. No checking for legal moves.</span>
<span class="Constant">]</span>
    cursor-to-next-line screen
    print-board screen, board
    cursor-to-next-line screen
    print screen, <span class="Constant">[Type in your move as &lt;from square&gt;-&lt;to square&gt;. For example: 'a2-a4'. Then press &lt;enter&gt;.</span>
<span class="Constant">]</span>
    cursor-to-next-line screen
    print screen <span class="Constant">[Hit 'q' to exit.</span>
<span class="Constant">]</span>
    <span class="Delimiter">{</span>
      cursor-to-next-line screen
      screen<span class="Special"> &lt;- </span>print screen, <span class="Constant">[move: ]</span>
      m:address:move, quit:boolean, error:boolean<span class="Special"> &lt;- </span>read-move buffered-stdin-in, screen
      <span class="muControl">break-if</span> quit, <span class="Constant">+quit:label</span>
      buffered-stdin-in<span class="Special"> &lt;- </span>clear buffered-stdin-in  <span class="Comment"># cleanup after error. todo: test this?</span>
      <span class="muControl">loop-if</span> error
    <span class="Delimiter">}</span>
    board<span class="Special"> &lt;- </span>make-move board, m
    screen<span class="Special"> &lt;- </span>clear-screen screen
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
<span class="Constant">  +quit</span>
]

<span class="SalientComment">## a board is an array of files, a file is an array of characters (squares)</span>

<span class="muRecipe">def</span> new-board initial-position:address:array:character<span class="muRecipe"> -&gt; </span>board:address:array:address:array:character [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  <span class="Comment"># assert(length(initial-position) == 64)</span>
  len:number<span class="Special"> &lt;- </span>length *initial-position
  correct-length?:boolean<span class="Special"> &lt;- </span>equal len, <span class="Constant">64</span>
  assert correct-length?, <span class="Constant">[chessboard had incorrect size]</span>
  <span class="Comment"># board is an array of pointers to files; file is an array of characters</span>
  board<span class="Special"> &lt;- </span>new <span class="Delimiter">{</span>(address array character): type<span class="Delimiter">}</span>, <span class="Constant">8</span>
  col:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Delimiter">{</span>
    done?:boolean<span class="Special"> &lt;- </span>equal col, <span class="Constant">8</span>
    <span class="muControl">break-if</span> done?
    file:address:array:character<span class="Special"> &lt;- </span>new-file initial-position, col
    *board<span class="Special"> &lt;- </span>put-index *board, col, file
    col<span class="Special"> &lt;- </span>add col, <span class="Constant">1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="muRecipe">def</span> new-file position:address:array:character, index:number<span class="muRecipe"> -&gt; </span>result:address:array:character [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  index<span class="Special"> &lt;- </span>multiply index, <span class="Constant">8</span>
  result<span class="Special"> &lt;- </span>new <span class="Constant">character:type</span>, <span class="Constant">8</span>
  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
  <span class="Delimiter">{</span>
    done?:boolean<span class="Special"> &lt;- </span>equal row, <span class="Constant">8</span>
    <span class="muControl">break-if</span> done?
    square:character<span class="Special"> &lt;- </span>index *position, index
    *result<span class="Special"> &lt;- </span>put-index *result, row, square
    row<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
    index<span class="Special"> &lt;- </span>add index, <span class="Constant">1</span>
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
]

<span class="muRecipe">def</span> print-board screen:address:screen, board:address:array:address:array:character<span class="muRecipe"> -&gt; </span>screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  row:number<span class="Special"> &lt;- </span>copy <span class="Constant">7</span>  <span class="Comment"># start printing from the top of the board</span>
  space:character<span class="Special"> &lt;- </span>copy <span class="Constant">32/space</span>
  <span class="Comment"># print each row</span>
  <span class="Delimiter">{</span>
    done?:boolean<span class="Special"> &lt;- </span>lesser-than row, <span class="Constant">0</span>
    <span class="muControl">break-if</span> done?
    <span class="Comment"># print rank number as a legend</span>
    rank:number<span class="Special"> &lt;- </span>add row, <span class="Constant">1</span>
    print-integer screen, rank
    print screen, <span class="Constant">[ | ]</span>
    <span class="Comment"># print each square in the row</span>
    col:number<span class="Special"> &lt;- </span>copy <span class="Constant">0</span>
    <span class="Delimiter">{</span>
      done?:boolean<span class="Special"> &lt;- </span>equal col:number, <span class="Constant">8</span>
      <span class="muControl">break-if</span> done?:boolean
      f:address:array:character<span class="Special"> &lt;- </span>index *board, col
      c:character<span class="Special"> &lt;- </span>index *f, row
      print screen, c
      print screen, space
      col<span class="Special"> &lt;- </span>add col, <span class="Constant">1</span>
      <span class="muControl">loop</span>
    <span class="Delimiter">}</span>
    row<span class="Special"> &lt;- </span>subtract row, <span class="Constant">1</span>
    cursor-to-next-line screen
    <span class="muControl">loop</span>
  <span class="Delimiter">}</span>
  <span class="Comment"># print file letters as legend</span>
  print screen, <span class="Constant">[  +----------------]</span>
  cursor-to-next-line screen
  print screen, <span class="Constant">[    a b c d e f g h]</span>
  cursor-to-next-line screen
]

<span class="muRecipe">def</span> initial-position<span class="muRecipe"> -&gt; </span>board:address:array:address:array:character [
  <span class="Constant">local-scope</span>
  <span class="Comment"># layout in memory (in raster order):</span>
  <span class="Comment">#   R P _ _ _ _ p r</span>
  <span class="Comment">#   N P _ _ _ _ p n</span>
  <span class="Comment">#   B P _ _ _ _ p b</span>
  <span class="Comment">#   Q P _ _ _ _ p q</span>
  <span class="Comment">#   K P _ _ _ _ p k</span>
  <span class="Comment">#   B P _ _ _ _ p B</span>
  <span class="Comment">#   N P _ _ _ _ p n</span>
  <span class="Comment">#   R P _ _ _ _ p r</span>
  initial-position:address:array:character<span class="Special"> &lt;- </span>new-array <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">81/Q</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">113/q</span>, <span class="Constant">75/K</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">107/k</span>, <span class="Constant">66/B</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">98/b</span>, <span class="Constant">78/N</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">110/n</span>, <span class="Constant">82/R</span>, <span class="Constant">80/P</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">32/blank</span>, <span class="Constant">112/p</span>, <span class="Constant">114/r</span>
<span class="CommentedCode">#?       82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r,</span>
<span class="CommentedCode">#?       78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span>
<span class="CommentedCode">#?       66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b, </span>
<span class="CommentedCode">#?       81/Q, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 113/q,</span>
<span class="CommentedCode">#?       75/K, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 107/k,</span>
<span class="CommentedCode">#?       66/B, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 98/b,</span>
<span class="CommentedCode">#?       78/N, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 110/n,</span>
<span class="CommentedCode">#?       82/R, 80/P, 32/blank, 32/blank, 32/blank, 32/blank, 112/p, 114/r</span>
  board<span class="Special"> &lt;- </span>new-board initial-position
]

<span class="muScenario">scenario</span> printing-the-board [
  assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span>
  run [
    <span class="Constant">local-scope</span>
    board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position
    screen:address:screen<span class="Special"> &lt;- </span>print-board screen:address:screen, board
  ]
  screen-should-contain [
  <span class="Comment">#  012345678901234567890123456789</span>
   <span class="Constant"> .8 | r n b q k b n r           .</span>
   <span class="Constant"> .7 | p p p p p p p p           .</span>
   <span class="Constant"> .6 |                           .</span>
   <span class="Constant"> .5 |                           .</span>
   <span class="Constant"> .4 |                           .</span>
   <span class="Constant"> .3 |                           .</span>
   <span class="Constant"> .2 | P P P P P P P P           .</span>
   <span class="Constant"> .1 | R N B Q K B N R           .</span>
   <span class="Constant"> .  +----------------           .</span>
   <span class="Constant"> .    a b c d e f g h           .</span>
   <span class="Constant"> .                              .</span>
   <span class="Constant"> .                              .</span>
  ]
]

<span class="SalientComment">## data structure: move</span>

<span class="muData">container</span> move [
  <span class="Comment"># valid range: 0-7</span>
  from-file:number
  from-rank:number
  to-file:number
  to-rank:number
]

<span class="Comment"># prints only error messages to screen</span>
<span class="muRecipe">def</span> read-move stdin:address:source:character, screen:address:screen<span class="muRecipe"> -&gt; </span>result:address:move, quit?:boolean, error?:boolean, stdin:address:source:character, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  from-file:number, quit?:boolean, error?:boolean<span class="Special"> &lt;- </span>read-file stdin, screen
  <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span>
  <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>
  <span class="Comment"># construct the move object</span>
  result:address:move<span class="Special"> &lt;- </span>new <span class="Constant">move:type</span>
  *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">from-file:offset</span>, from-file
  from-rank:number, quit?, error?<span class="Special"> &lt;- </span>read-rank stdin, screen
  <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span>
  <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>
  *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">from-rank:offset</span>, from-rank
  error?<span class="Special"> &lt;- </span>expect-from-channel stdin, <span class="Constant">45/dash</span>, screen
  <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>
  to-file:number, quit?, error?<span class="Special"> &lt;- </span>read-file stdin, screen
  <span class="muControl">return-if</span> quit?:boolean, <span class="Constant">0/dummy</span>
  <span class="muControl">return-if</span> error?:boolean, <span class="Constant">0/dummy</span>
  *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">to-file:offset</span>, to-file
  to-rank:number, quit?, error?<span class="Special"> &lt;- </span>read-rank stdin, screen
  <span class="muControl">return-if</span> quit?, <span class="Constant">0/dummy</span>
  <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>
  *result<span class="Special"> &lt;- </span>put *result, <span class="Constant">to-rank:offset</span>, to-rank
  error?<span class="Special"> &lt;- </span>expect-from-channel stdin, <span class="Constant">10/newline</span>, screen
  <span class="muControl">return-if</span> error?, <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>
]

<span class="Comment"># valid values for file: 0-7</span>
<span class="muRecipe">def</span> read-file stdin:address:source:character, screen:address:screen<span class="muRecipe"> -&gt; </span>file:number, quit:boolean, error:boolean, stdin:address:source:character, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  c:character, eof?:boolean, stdin<span class="Special"> &lt;- </span>read stdin
  <span class="muControl">return-if</span> eof?, <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">{</span>
    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">81/Q</span>
    <span class="muControl">break-unless</span> q-pressed?
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    q-pressed?<span class="Special"> &lt;- </span>equal c, <span class="Constant">113/q</span>
    <span class="muControl">break-unless</span> q-pressed?
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    empty-fake-keyboard?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">0/eof</span>
    <span class="muControl">break-unless</span> empty-fake-keyboard?
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10/newline</span>
    <span class="muControl">break-unless</span> newline?
    print screen, <span class="Constant">[that's not enough]</span>
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  file:number<span class="Special"> &lt;- </span>subtract c, <span class="Constant">97/a</span>
  <span class="Comment"># 'a' &lt;= file &lt;= 'h'</span>
  <span class="Delimiter">{</span>
    above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal file, <span class="Constant">0</span>
    <span class="muControl">break-if</span> above-min
    print screen, <span class="Constant">[file too low: ]</span>
    print screen, c
    cursor-to-next-line screen
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    below-max:boolean<span class="Special"> &lt;- </span>lesser-than file, <span class="Constant">8</span>
    <span class="muControl">break-if</span> below-max
    print screen, <span class="Constant">[file too high: ]</span>
    print screen, c
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  <span class="muControl">return</span> file, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span>
]

<span class="Comment"># valid values for rank: 0-7</span>
<span class="muRecipe">def</span> read-rank stdin:address:source:character, screen:address:screen<span class="muRecipe"> -&gt; </span>rank:number, quit?:boolean, error?:boolean, stdin:address:source:character, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  c:character, eof?:boolean, stdin<span class="Special"> &lt;- </span>read stdin
  <span class="muControl">return-if</span> eof?, <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">{</span>
    q-pressed?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">8/Q</span>
    <span class="muControl">break-unless</span> q-pressed?
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    q-pressed?<span class="Special"> &lt;- </span>equal c, <span class="Constant">113/q</span>
    <span class="muControl">break-unless</span> q-pressed?
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">1/quit</span>, <span class="Constant">0/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    newline?:boolean<span class="Special"> &lt;- </span>equal c, <span class="Constant">10</span>  <span class="Comment"># newline</span>
    <span class="muControl">break-unless</span> newline?
    print screen, <span class="Constant">[that's not enough]</span>
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  rank:number<span class="Special"> &lt;- </span>subtract c, <span class="Constant">49/'1'</span>
  <span class="Comment"># assert'1' &lt;= rank &lt;= '8'</span>
  <span class="Delimiter">{</span>
    above-min:boolean<span class="Special"> &lt;- </span>greater-or-equal rank, <span class="Constant">0</span>
    <span class="muControl">break-if</span> above-min
    print screen, <span class="Constant">[rank too low: ]</span>
    print screen, c
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  <span class="Delimiter">{</span>
    below-max:boolean<span class="Special"> &lt;- </span>lesser-or-equal rank, <span class="Constant">7</span>
    <span class="muControl">break-if</span> below-max
    print screen, <span class="Constant">[rank too high: ]</span>
    print screen, c
    <span class="muControl">return</span> <span class="Constant">0/dummy</span>, <span class="Constant">0/quit</span>, <span class="Constant">1/error</span>
  <span class="Delimiter">}</span>
  <span class="muControl">return</span> rank, <span class="Constant">0/quit</span>, <span class="Constant">0/error</span>
]

<span class="Comment"># read a character from the given channel and check that it's what we expect</span>
<span class="Comment"># return true on error</span>
<span class="muRecipe">def</span> expect-from-channel stdin:address:source:character, expected:character, screen:address:screen<span class="muRecipe"> -&gt; </span>result:boolean, stdin:address:source:character, screen:address:screen [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  c:character, eof?:boolean, stdin<span class="Special"> &lt;- </span>read stdin
  <span class="muControl">return-if</span> eof? <span class="Constant">1/true</span>
  <span class="Delimiter">{</span>
    match?:boolean<span class="Special"> &lt;- </span>equal c, expected
    <span class="muControl">break-if</span> match?
    print screen, <span class="Constant">[expected character not found]</span>
  <span class="Delimiter">}</span>
  result<span class="Special"> &lt;- </span>not match?
]

<span class="muScenario">scenario</span> read-move-blocking [
  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
  run [
    <span class="Constant">local-scope</span>
    source:address:source:character, sink:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">2/capacity</span>
    read-move-routine:number/routine<span class="Special"> &lt;- </span>start-running read-move, source, screen:address:screen
    <span class="Comment"># 'read-move' is waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state:number<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after coming up (before any keys were pressed)]</span>
    <span class="Comment"># press 'a'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">97/a</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' still waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after rank 'a']</span>
    <span class="Comment"># press '2'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">50/'2'</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' still waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after file 'a2']</span>
    <span class="Comment"># press '-'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">45/'-'</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' still waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after hyphen 'a2-']</span>
    <span class="Comment"># press 'a'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">97/a</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' still waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after rank 'a2-a']</span>
    <span class="Comment"># press '4'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">52/'4'</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' still waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to pause after file 'a2-a4']</span>
    <span class="Comment"># press 'newline'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">10</span>  <span class="Comment"># newline</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' now completes</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    completed?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">1/completed</span>
    assert completed?, <span class="Constant">[ </span>
<span class="Constant">F read-move-blocking: routine failed to terminate on newline]</span>
    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
  ]
  trace-should-contain [
    test: reached end
  ]
]

<span class="muScenario">scenario</span> read-move-quit [
  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
  run [
    <span class="Constant">local-scope</span>
    source:address:source:character, sink:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">2/capacity</span>
    read-move-routine:number<span class="Special"> &lt;- </span>start-running read-move, source, screen:address:screen
    <span class="Comment"># 'read-move' is waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state:number<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-quit: routine failed to pause after coming up (before any keys were pressed)]</span>
    <span class="Comment"># press 'q'</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">113/q</span>
    restart read-move-routine
    <span class="Comment"># 'read-move' completes</span>
    wait-for-routine read-move-routine
    read-move-state<span class="Special"> &lt;- </span>routine-state read-move-routine
    completed?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">1/completed</span>
    assert completed?, <span class="Constant">[ </span>
<span class="Constant">F read-move-quit: routine failed to terminate on 'q']</span>
    trace <span class="Constant">1</span>, <span class="Constant">[test]</span>, <span class="Constant">[reached end]</span>
  ]
  trace-should-contain [
    test: reached end
  ]
]

<span class="muScenario">scenario</span> read-move-illegal-file [
  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
  run [
    <span class="Constant">local-scope</span>
    source:address:source:character, sink:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">2/capacity</span>
    read-move-routine:number<span class="Special"> &lt;- </span>start-running read-move, source, screen:address:screen
    <span class="Comment"># 'read-move' is waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state:number<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">50/'2'</span>
    restart read-move-routine
    wait-for-routine read-move-routine
  ]
  screen-should-contain [
   <span class="Constant"> .file too low: 2     .</span>
   <span class="Constant"> .                    .</span>
  ]
]

<span class="muScenario">scenario</span> read-move-illegal-rank [
  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
  run [
    <span class="Constant">local-scope</span>
    source:address:source:character, sink:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">2/capacity</span>
    read-move-routine:number<span class="Special"> &lt;- </span>start-running read-move, source, screen:address:screen
    <span class="Comment"># 'read-move' is waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state:number<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">97/a</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">97/a</span>
    restart read-move-routine
    wait-for-routine read-move-routine
  ]
  screen-should-contain [
   <span class="Constant"> .rank too high: a    .</span>
   <span class="Constant"> .                    .</span>
  ]
]

<span class="muScenario">scenario</span> read-move-empty [
  assume-screen <span class="Constant">20/width</span>, <span class="Constant">2/height</span>
  run [
    <span class="Constant">local-scope</span>
    source:address:source:character, sink:address:sink:character<span class="Special"> &lt;- </span>new-channel <span class="Constant">2/capacity</span>
    read-move-routine:number<span class="Special"> &lt;- </span>start-running read-move, source, screen:address:screen
    <span class="Comment"># 'read-move' is waiting for input</span>
    wait-for-routine read-move-routine
    read-move-state:number<span class="Special"> &lt;- </span>routine-state read-move-routine
    waiting?:boolean<span class="Special"> &lt;- </span>equal read-move-state, <span class="Constant">3/waiting</span>
    assert waiting?, <span class="Constant">[ </span>
<span class="Constant">F read-move-file: routine failed to pause after coming up (before any keys were pressed)]</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">10/newline</span>
    sink<span class="Special"> &lt;- </span>write sink, <span class="Constant">97/a</span>
    restart read-move-routine
    wait-for-routine read-move-routine
  ]
  screen-should-contain [
   <span class="Constant"> .that's not enough   .</span>
   <span class="Constant"> .                    .</span>
  ]
]

<span class="muRecipe">def</span> make-move board:address:array:address:array:character, m:address:move<span class="muRecipe"> -&gt; </span>board:address:array:address:array:character [
  <span class="Constant">local-scope</span>
  <span class="Constant">load-ingredients</span>
  from-file:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">from-file:offset</span>
  from-rank:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">from-rank:offset</span>
  to-file:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">to-file:offset</span>
  to-rank:number<span class="Special"> &lt;- </span>get *m, <span class="Constant">to-rank:offset</span>
  from-f:address:array:character<span class="Special"> &lt;- </span>index *board, from-file
  to-f:address:array:character<span class="Special"> &lt;- </span>index *board, to-file
  src:character/square<span class="Special"> &lt;- </span>index *from-f, from-rank
  *to-f<span class="Special"> &lt;- </span>put-index *to-f, to-rank, src
  *from-f<span class="Special"> &lt;- </span>put-index *from-f, from-rank, <span class="Constant">32/space</span>
]

<span class="muScenario">scenario</span> making-a-move [
  assume-screen <span class="Constant">30/width</span>, <span class="Constant">12/height</span>
  run [
    <span class="Constant">local-scope</span>
    board:address:array:address:array:character<span class="Special"> &lt;- </span>initial-position
    move:address:move<span class="Special"> &lt;- </span>new <span class="Constant">move:type</span>
    *move<span class="Special"> &lt;- </span>merge <span class="Constant">6/g</span>, <span class="Constant">1/'2'</span>, <span class="Constant">6/g</span>, <span class="Constant">3/'4'</span>
    board<span class="Special"> &lt;- </span>make-move board, move
    screen:address:screen<span class="Special"> &lt;- </span>print-board screen:address:screen, board
  ]
  screen-should-contain [
  <span class="Comment">#  012345678901234567890123456789</span>
   <span class="Constant"> .8 | r n b q k b n r           .</span>
   <span class="Constant"> .7 | p p p p p p p p           .</span>
   <span class="Constant"> .6 |                           .</span>
   <span class="Constant"> .5 |                           .</span>
   <span class="Constant"> .4 |             P             .</span>
   <span class="Constant"> .3 |                           .</span>
   <span class="Constant"> .2 | P P P P P P   P           .</span>
   <span class="Constant"> .1 | R N B Q K B N R           .</span>
   <span class="Constant"> .  +----------------           .</span>
   <span class="Constant"> .    a b c d e f g h           .</span>
   <span class="Constant"> .                              .</span>
  ]
]
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->