; TurtleInGridLand (Lesson 12 - Predicates)
; -----------------------------------------


; Symbolic Constants
; -------- ---------

; SETPENCOLOR values
to black
  output 0
  end
to green
  output 2
  end
to white
  output 7
  end


; keyPressed key values
to downArrowKey
  output 65537
  end
to leftArrowKey
  output 65538
  end
to rightArrowKey
  output 65539
  end
to upArrowKey
  output 65536
  end

  
; color for a cell's background
to gridCellColor
  output white
  end

; color of grid's frame
to gridFrameColor
  output black
  end

; size of the sides of a grid cell
to gridCellSize
  output 40
  end

; one-half the size of a side of a grid cell
to gridHafCellSiz
  output quotient gridCellSize 2
  end

; number of columns in the grid
to gridNumCol
  output 12
  end

; number of rows in the grid
to gridNumRow
  output 8
  end

; number of cells in the grid
to gridNumCells
  output product gridNumCol gridNumRow
  end

; height of grid in turtle steps
to gridHeight
  output product gridNumRow gridCellSize
  end

; width of grid in turtle steps
to gridWidth
  output product gridNumCol gridCellSize
  end

 ; X coordinate for left side of the grid
 to gridLeftX
   output minus product gridCellSize (quotient gridNumCol 2)
   end

 ; X coordinate for right side of the grid
 to gridRightX
   output difference (sum gridLeftX gridWidth) 1
   end

 ; Y coordinate for bottom of the grid
 to gridBottomY
   output minus product gridCellSize (quotient gridNumRow 2)
   end

 ; Y coordinate for top of the grid
 to gridTopY
   output difference (sum gridBottomY gridHeight) 1
   end


; Grid Procedures
; ---- ----------

; move the turtle to the top-left corner of the grid
to gridGotoTopLeft
  penup
  setxy gridLeftX gridTopY
  end

; move the turtle to the bottom-left corner of the cell
; specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
to gridGotoCell :idx
  gridGotoTopLeft
  setheading 180
  forward product gridCellSize (int quotient :idx gridNumCol)
  forward gridCellSize
  setheading 90
  forward product gridCellSize (remainder :idx gridNumCol)
  end

; move the turtle to the bottom-left corner of the cell
; specified by the two-number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
to gridGotoRowColCell :rowCol
  gridGotoTopLeft
  setheading 180
  forward product gridCellSize (first :rowCol)
  forward gridCellSize
  setheading 90
  forward product gridCellSize (last :rowCol)
  end

; with the turtle at the bottom-left corner of
; a cell, move it to the center of the cell
to gotoCellCtrHelper
  setheading 90 forward gridHafCellSiz
  left 90 forward gridHafCellSiz
  end

; move the turtle to the center of cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
to gridGotoCellCtr :idx
  gridGotoCell :idx
  gotoCellCtrHelper
  end

; move the turtle to the center of the cell specified by the
; two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
to gridGotoRowColCellCtr :rowCol
  gridGotoRowColCell :rowCol
  gotoCellCtrHelper
  end

; with the turtle at the center of a cell,
; repaint the cell with a specified background color
to fillCellHelper :color
  setpensize gridCellSize setpencolor :color
  setheading 0 forward gridHafCellSiz 
  pendown back gridCellSize
  left 90 penup forward gridHafCellSiz
  setpensize 1 setpencolor gridFrameColor setheading 0
  pendown repeat 4 [forward gridCellSize right 90]
  end

; draw/redraw the cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
; the :color input specifies the cell's background color
to gridCellFill :idx :color
  gridGotoCellCtr :idx
  fillCellHelper :color
  end

; draw/redraw the cell specified by the two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
; the :color input specifies the cell's background color
to gridRowColCellFill :rowCol :color
  gridGotoRowColCellCtr :rowCol
  fillCellHelper :color
  end

; with the turtle at the bottom-left corner of a cell, label
; the cell with a specified character in a specified color
to labelCellHelper :ch :color
  setheading 0
  setlabelheight difference gridCellSize 8
  forward 4
  right 90
  forward quotient (difference gridCellSize (labelwidth :ch)) 2
  setpencolor :color
  label :ch
  end

; label the cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
; the :ch input, the label, is a single character word
; the :color input specifies the character's color
to gridCellLabel :idx :ch :color
  gridGotoCell :idx
  labelCellHelper :ch :color
  end

; label the cell specified by by the two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
; the :ch input, the label, is a single character word
; the :color input specifies the character's color
to gridRowColCellLabel :rowCol :ch :color
  gridGotoRowColCell :rowCol
  labelCellHelper :ch :color
  end


;draw the grid
to gridPaint
  gridGotoTopLeft
  setheading 180 forward quotient gridHeight 2 setheading 90
  setpensize gridHeight setpencolor gridCellColor
  pendown forward gridWidth
  gridGotoTopLeft
  setpensize 1 setpencolor gridFrameColor
  setheading 180 pendown
  repeat gridNumRow [fd gridCellSize lt 90 fd gridWidth bk gridWidth rt 90]
  gridGotoTopLeft
  setheading 90 pendown
  repeat gridNumCol [fd gridCellSize rt 90 fd gridHeight bk gridHeight lt 90]
  end


;Output a column number given an X TurtleSpace coordinate
;*note* X is assumed to be within the bounds of the grid.
;       Verify this before invoking gridXtoColNum
to gridXtoColNum :x
  output int quotient (difference :x gridLeftX) gridCellSize
  end

;Output a row number given a Y TurtleSpace coordinate
;*note* Y is assumed to be within the bounds of the grid.
;       Verify this before invoking gridXtoColNum
to gridYtoRowNum :y
  output int quotient (difference gridTopY :y) gridCellSize
  end

;Output the index of the cell given TurtleSpace X and Y coordinates
;*note* the X and Y coordinates are assumed to be within the bounds
;       of the grid. They should be checked before invoking
;       gridIndexForXY
to gridIndexForXY :x :y
  output sum (product (gridYtoRowNum :y) gridNumCol) gridXtoColNum :x  
  end

;Output a sentence of row and column numbers identifying a cell
;given TurtleSpace X and Y coordinates.
;*note* the X and Y coordinates are assumed to be within the bounds
;       of the grid. They should be checked before invoking
;       gridRowColForXY
to gridRowColForXY :x :y
  output sentence (gridYtoRowNum :y) (gridXtoColNum :x)
  end

; Output true if the input X and Y coordinates are within the bounds
; of the grid, otherwise output false
to gridContainsXY? :x :y
  if less? :x gridLeftX [output "false]
  if less? :y gridBottomY [output "false]
  if greater? :x gridRightX [output "false]
  if greater? :y gridTopY [output "false]
  output "true
  end

; Output true if the input point (a two number [X Y] sentence) is
; within the bounds of the grid, otherwise outputs false
to gridContainsPos? :point
  if less? (first :point) gridLeftX [output "false]
  if less? (last :point) gridBottomY [output "false]
  if greater? (first :point) gridRightX [output "false]
  if greater? (last :point) gridTopY [output "false]
  output "true
  end


; TurtleInGridLand Stuff
; ---------------- -----

; respond to a key pressed event
; move the turtle backward one cell if downArrow key is pressed
; move the turtle forward one cell if upArrow key is pressed
; rotate the turtle left 90 degrees if leftArrow key is pressed
; rotate the turtle rigth 90 degrees if rightArrow key is pressed
to keyPressed :keyNum
  if equal? :keyNum upArrowKey [forward gridCellSize]
  if equal? :keyNum leftArrowKey [left 90]
  if equal? :keyNum rightArrowKey [right 90]
  if equal? :keyNum downArrowKey [back gridCellSize]
  end

; MAIN
; ----
to main
  hideturtle home clean
  gridPaint
  gridGotoCellCtr random gridNumCells
  setheading 0 repeat (random 4) [right 90]
  setpencolor green showturtle penup
  end

main