Skip to content

Instantly share code, notes, and snippets.

@johnlettman-old
Created January 26, 2013 15:19
Show Gist options
  • Save johnlettman-old/4642871 to your computer and use it in GitHub Desktop.
Save johnlettman-old/4642871 to your computer and use it in GitHub Desktop.
Langston's Ant (old program)
HTMLCanvasElement::relativeMouseCoordinates = (event) ->
x = new Number()
y = new Number()
if event.x isnt undefined and event.y isnt undefined
x = event.x
y = event.y
else
x = event.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft
y = event.clientY + document.body.scrollTop +
document.documentElement.scrollTop
x -= this.offsetLeft
y -= this.offsetTop
return {x:x, y:y}
Number::mod = (n) -> ((this % n) + n) % n # Stupid Javascript modulus fix.
class window.LangstonsAnt
TURN_LEFT: 0x1
TURN_RIGHT: 0x2
DIRECTION_N: 0x0
DIRECTION_E: 0x1
DIRECTION_S: 0x2
DIRECTION_W: 0x3
antColour: 'red'
gridColour: 'grey'
moves: 0
movementRules: []
__movementRulesLocation: 0
__xLimit: 0
__yLimit: 0
__grid: []
__antLocation: [0,0]
__antDirection: @DIRECTION_N
__callback_dirchange: null
__callback_locchange: null
__callback_moveschange: null
constructor: (canvasID, @squareSize = 5) ->
@canvasElement = document.getElementById canvasID
@canvasContext = @canvasElement.getContext '2d'
@canvasElement.onclick = (e) =>
realCoords = @canvasElement.relativeMouseCoordinates(e)
gridX = Math.round((realCoords.x - (@squareSize / 2)) / @squareSize)
gridY = Math.round((realCoords.y - (@squareSize / 2)) / @squareSize)
if not (gridX is @__antLocation[0] and gridY is @__antLocation[1])
this.__flip gridX, gridY
# Initialize defaults
@__antDirection = @DIRECTION_N
@movementRules.push { white:@TURN_RIGHT, black:@TURN_LEFT }
generateGrid: () ->
@canvasContext.clearRect(0, 0, @canvasElement.width, @canvasElement.height);
@canvasContext.beginPath()
@canvasContext.lineWidth = 1
for xCoord in [0..@canvasElement.width] by @squareSize
@canvasContext.moveTo xCoord, 0
@canvasContext.lineTo xCoord, @canvasElement.height
@__xLimit++
for yCoord in [0..@canvasElement.height] by @squareSize
@canvasContext.moveTo 0, yCoord
@canvasContext.lineTo @canvasElement.width, yCoord
@__yLimit++
@__yLimit -= 2
@__xLimit -= 1
@canvasContext.strokeStyle = @gridColour
@canvasContext.stroke()
for row in [0..@__xLimit]
@__grid.push []
for column in [0..@__yLimit]
@__grid[row].push 0
this.placeAnt()
reset: () -> this.generateGrid()
setLocationCallback: (func) -> @__callback_locchange = func
setDirectionCallback: (func) -> @__callback_dirchange = func
setMovesCallback: (func) -> @__callback_moveschange = func
addMovementRule: (rule) ->
if (rule.white is @TURN_LEFT or rule.white is @TURN_RIGHT) and
(rule.black is @TURN_LEFT or rule.black is @TURN_RIGHT) then @movementRules.push rule
addMovementRules: (ruleList) ->
for rule in ruleList
this.addMovementRule rule
return
move: (iterations = 0) ->
@moves++
@__antPrev = @__antLocation
# Turn according to the square rules.
switch @__antDirection
when @DIRECTION_N
if (@__antPrev[1] - 1) < 0
this.__turn @__grid[ @__antPrev[0] ][ @__yLimit ]
else
this.__turn @__grid[ @__antPrev[0] ][ @__antPrev[1] - 1 ]
when @DIRECTION_E
if (@__antPrev[0] + 1) > @__xLimit
this.__turn @__grid[ 0 ][ @__antPrev[1] ]
else
this.__turn @__grid[ @__antPrev[0] + 1 ][ @__antPrev[1] ]
when @DIRECTION_S
if (@__antPrev[1] + 1) > @__yLimit
this.__turn @__grid[ @__antPrev[0] ][ 0 ]
else
this.__turn @__grid[ @__antPrev[0] ][ @__antPrev[1] + 1 ]
when @DIRECTION_W
if (@__antPrev[0] - 1) < 0
this.__turn @__grid[ @__xLimit ][ @__antPrev[1] ]
else
this.__turn @__grid[ @__antPrev[0] - 1 ][ @__antPrev[1] ]
switch @__antDirection
when @DIRECTION_N
if (@__antPrev[1] - 1) < 0
@__antLocation = [@__antPrev[0], @__yLimit]
else
@__antLocation = [@__antPrev[0], @__antPrev[1] - 1]
when @DIRECTION_E
if (@__antPrev[0] + 1) > @__xLimit
@__antLocation = [0, @__antPrev[1]]
else
@__antLocation = [@__antPrev[0] + 1, @__antPrev[1]]
when @DIRECTION_S
if (@__antPrev[1] + 1) > @__yLimit
@__antLocation = [@__antPrev[0], 0]
else
@__antLocation = [@__antPrev[0], @__antPrev[1] + 1]
when @DIRECTION_W
if (@__antPrev[0] - 1) < 0
@__antLocation = [@__xLimit, @__antPrev[1]]
else
@__antLocation = [@__antPrev[0] - 1, @__antPrev[1]]
this.placeAnt @__antLocation[0], @__antLocation[1]
this.__flip @__antPrev[0], @__antPrev[1]
@__callback_locchange @__antLocation
@__callback_dirchange @__antDirection
@__callback_moveschange @moves
iterations--
if iterations > 0
while iterations > 0
this.move()
iterations--
return
placeAnt: (x = -1, y = -1) ->
if (x < 0 or y < 0) or (x > @__xLimit or y > @__yLimit)
x = Math.round @__xLimit / 2
y = Math.round @__yLimit / 2
@__antLocation = [x,y]
this.__drawAnt x, y
__turn: (encounteredSquare) ->
turnDirection = @movementRules[@__movementRulesLocation].white if encounteredSquare is 0
turnDirection = @movementRules[@__movementRulesLocation].black if encounteredSquare is 1
@__antDirection = (@__antDirection + 1).mod(4) if turnDirection is @TURN_RIGHT
@__antDirection = (@__antDirection - 1).mod(4) if turnDirection is @TURN_LEFT
@__movementRulesLocation = (@__movementRulesLocation + 1) % @movementRules.length
return
__flip: (x, y) ->
if @__grid[x][y] is 1 then @__grid[x][y] = 0
else @__grid[x][y] = 1
if @__grid[x][y] is 1 then this.__drawSquare x, y, 'black'
else this.__drawSquare x, y, 'white'
__drawAnt: (x = -1, y = -1) ->
x = @__antLocation[0] if x < 0
y = @__antLocation[1] if y < 0
this.__drawSquare x, y, @antColour
squareMiddle = Math.round(@squareSize / 2)
@canvasContext.fillStyle = 'black'
switch @__antDirection
when @DIRECTION_N
@canvasContext.fillRect(
(x * @squareSize) + Math.round(squareMiddle / 2),
(y * @squareSize) + 1, squareMiddle, squareMiddle)
when @DIRECTION_E
@canvasContext.fillRect(
(x * @squareSize) + (@squareSize - squareMiddle),
(y * @squareSize) + Math.round(squareMiddle / 2),
squareMiddle, squareMiddle)
when @DIRECTION_S
@canvasContext.fillRect(
(x * @squareSize) + Math.round(squareMiddle / 2),
(y * @squareSize) + squareMiddle,
squareMiddle, squareMiddle)
when @DIRECTION_W
@canvasContext.fillRect(
(x * @squareSize) + 1,
(y * @squareSize) + Math.round(squareMiddle / 2),
squareMiddle, squareMiddle)
__drawSquare: (x, y, colour = null) ->
if colour is null
colour = 'white' if @__grid[x][y] is 0
colour = 'black' if @__grid[x][y] is 1
@canvasContext.fillStyle = colour
@canvasContext.fillRect (x * @squareSize) + 1, (y * @squareSize) + 1,
@squareSize - 1, @squareSize - 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment