export const turtle_init = { position: [0, 0], heading: 0, pendown: true, pencolor: "white", penwidth: 1, visible: true } export const turtle_radius = 20 export const turtle_angle = 0.385 let turtle_color = [255, 255, 255, 150] export function get_turtle_color () { return turtle_color } export function set_turtle_color (new_color) { turtle_color = new_color } export const colors = { black: [0, 0, 0, 255], silver: [192, 192, 192, 255], gray: [128, 128, 128, 255], grey: [128, 128, 128, 255], white: [255, 255, 255, 255], maroon: [128, 0, 0, 255], red: [255, 0, 0, 255], purple: [128, 0, 128, 255], fuchsia: [255, 0, 255, 255], green: [0, 128, 0, 255], lime: [0, 255, 0, 255], olive: [128, 128, 0, 255], yellow: [255, 255, 0, 255], navy: [0, 0, 128, 255], blue: [0, 0, 255, 255], teal: [0, 128, 128, 255], aqua: [0, 255, 255, 255], } export function resolve_color (color) { if (typeof color === 'string') return colors[color] if (typeof color === 'number') return [color, color, color, 255] if (Array.isArray(color)) return color return [0, 0, 0, 255] // default to black? } export let background_color = "black" export function add (v1, v2) { const [x1, y1] = v1 const [x2, y2] = v2 return [x1 + x2, y1 + y2] } export function mult (vector, scalar) { const [x, y] = vector return [x * scalar, y * scalar] } export function unit_of (heading) { const turns = -heading + 0.25 const radians = turn_to_rad(turns) return [Math.cos(radians), Math.sin(radians)] } export function command_to_state (prev_state, curr_command) { const [verb] = curr_command switch (verb) { case "goto": { const [_, x, y] = curr_command return {...prev_state, position: [x, y]} } case "home": { return {...prev_state, position: [0, 0], heading: 0} } case "right": { const [_, angle] = curr_command const {heading} = prev_state return {...prev_state, heading: heading + angle} } case "left": { const [_, angle] = curr_command const {heading} = prev_state return {...prev_state, heading: heading - angle} } case "forward": { const [_, steps] = curr_command const {heading, position} = prev_state const unit = unit_of(heading) const move = mult(unit, steps) return {...prev_state, position: add(position, move)} } case "back": { const [_, steps] = curr_command const {heading, position} = prev_state const unit = unit_of(heading) const move = mult(unit, -steps) return {...prev_state, position: add(position, move)} } case "penup": { return {...prev_state, pendown: false} } case "pendown": { return {...prev_state, pendown: true} } case "penwidth": { const [_, width] = curr_command return {...prev_state, penwidth: width} } case "pencolor": { const [_, color] = curr_command return {...prev_state, pencolor: color} } case "setheading": { const [_, heading] = curr_command return {...prev_state, heading: heading} } case "loadstate": { // console.log("LOADSTATE: ", curr_command) const [_, [x, y], heading, visible, pendown, penwidth, pencolor] = curr_command return {position: [x, y], heading, visible, pendown, penwidth, pencolor} } case "show": { return {...prev_state, visible: true} } case "hide": { return {...prev_state, visible: false} } case "background": { background_color = curr_command[1] return prev_state } } } export function eq_vect (v1, v2) { const [x1, y1] = v1 const [x2, y2] = v2 return (x1 === x2) && (y1 === y2) } export function eq_color (c1, c2) { if (c1 === c2) return true const res1 = resolve_color(c1) const res2 = resolve_color(c2) for (let i = 0; i < res1.length; ++i) { if (res1[i] !== res2[i]) return false } return true } export function rotate (vector, heading) { const radians = turn_to_rad(heading) const [x, y] = vector return [ (x * Math.cos (radians)) - (y * Math.sin (radians)), (x * Math.sin (radians)) + (y * Math.cos (radians)) ] } export function turn_to_rad (heading) { return (heading % 1) * 2 * Math.PI } export function turn_to_deg (heading) { return (heading % 1) * 360 } export function last (arr) { return arr[arr.length - 1] }