Langton's ant: Difference between revisions

Content added Content deleted
(→‎{{header|Processing}}: adding Processing Python mode)
Line 4,226: Line 4,226:
Same as D entry (textual version)
Same as D entry (textual version)
</pre>
</pre>

=={{header|LC-3}}==
<lang LC-3>

.orig x3000
ld r1, ASCIIDIFF1

; user input for grid size
lea r0, STGRIDSIZE
puts
in

add r0, r0, r1
add r0, r0, #-1
brz SELECTED100
ld r0, GRID300
st r0, GRIDSIZE
brnzp GRIDSELECTED

SELECTED100
ld r0, GRID100
st r0, GRIDSIZE

GRIDSELECTED

; User input for number of additional ants
lea r0, STHOWMANY
puts
in
add r1, r1, r0 ; r1 = number of additional ants
add r1, r1, #1
st r1, LIVINGANTS

; INITIALIZE FIRST ANT
and r7, r7, x0
add r7, r7, #9 ; loop counter for the other ants

and r1, r1, x0  ; x and y coordinates go in here
and r3, r3, x0  ; to be mapped to a cell id

; check grid size for starting coordinates
ld r4, GRIDSIZE
ld r6, GRID100
not r6, r6
add r6, r6, #1
add r6, r6, r4  ; grid size - 100
brz GRID100B

ld r1, START300
ld r3, START300
brnzp FIRSTANTCOORDINATES

GRID100B
ld r1, START100
ld r3, START100

FIRSTANTCOORDINATES

JSR MAPPY   ; takes r1 and r3 values, converts to cell id in r5

ld r6, LIVEANTTEMPLATE  ; = x8000, alive and facing north
add r6, r6, r5  ; complete antword for ant 1
lea r4, ANTWORD
str r6, r4, #0  ; put first ant in base address of ANTWORD array


ld r2, LIVINGANTS
ANTSETUPLOOP
add r4, r4, #1  ;   increment address of ant

add r2, r2, #-1
brnz INITIALIZEDEAD
JSR ANTCOORDS
JSR MAPPY
ld r6, LIVEANTTEMPLATE
add r6, r5, r6
brnzp READYTOSTORE

INITIALIZEDEAD
and r6, r6, x0

READYTOSTORE
str r6, r4, #0


add r7, r7, #-1
brnz DONESETUP
brnzp ANTSETUPLOOP

DONESETUP







BIGMOVELOOP ; one iteration of this loop moves all 10 ants (doing nothing if they're dead)
ld r1, LIVINGANTS
brz EVERYONEISDEAD
ld r1, ANTWORD


; FOR LOOP TO MOVE ALL 10 ANTS





ld r1, STEPCOUNT
add r1, r1, #1
st r1, STEPCOUNT

BRNZP BIGMOVELOOP
EVERYONEISDEAD ; :(




halt
STGRIDSIZE .stringz "Grid size? 1 for 100, 3 for 300 "
STHOWMANY .stringz "How many additional ants? "
ASCIIDIFF1 .fill #-48
SUBTEMP1 .fill #0
LIVINGANTS .fill #0
GRIDSIZE .fill #0
GRID100 .fill #100
GRID300 .fill #300
STEPCOUNT .fill #0
ANTWORD .blkw #10
START100 .fill #50
START300 .fill #150
LIVEANTTEMPLATE .fill x8000
ANTCOORDTEMP .fill #0
ANTCOORDTEMP2 .fill #0









;************************************************************************
;************************************************************************
;                             SUBROUTINES
;************************************************************************
;************************************************************************

; SUBROUTINE
ANTSONTHEMOVE
; [1] check if dead
; [2] extract current location
; [3] extract current direction
; [4] check current colour
; [5] turn
; [7] change location or kill

; INPUT: R1:
address of ant
;        R4:
grid size

; LOCAL: R2: ant word
;           R3: cell id of ant

st r2, MOVETEMP2
st r3, MOVETEMP3
st r5, MOVETEMP5
st r6, MOVETEMP6
st r7, MOVETEMP7
ldr r2, r1, #0 ; r2 = copy of ant-word

; [1] CHECK FOR DEATH. word for dead ants == x0000
add r2, r2, #0
brz ENDOFMOVE ; if ant-word + 0 == 0, ant is dead.

; [2] extract current location
ld r3, IDMASK ; for getting rid of first 3 bits of ant-word, leaving only location
and r3, r2, r3 ; r3 = cell id of ant

; [4] check current colour and flip it


jsr FLIPPITY    ; flips bit, puts original colour in R5
                ; white/0: turn right; black/1: turn left

; [5] turn the ant according to pre-flipped colour

add r0, r5, #0
brnp LEFTTURN

jsr TAKEARIGHTTURN
brnzp DONETURNING

LEFTTURN
jsr TAKEALEFTTURN
DONETURNING

; [7] change location and kill

ldr r2, r1, #0 ; reload modified antword from memory

ld r5, SOUTH    ; butmasks
ld r6, EAST

and r5, r5, r2
and r6, r6, r2  ; isolating the two direction bits, 2b and 3b, to determine direction

add r5, r5, #0  ;    check if 2b is 0
brnp SECTIOND   ;
add r6, r6, #0  ;   check if 3b is 0
brnp SECTIONC


; if both are zero, direction is north
;; if cell id <= grid size, ant is already at the top and will die
not r0, r4
add r0, r0, #1  ; r0 = negative grid size
add r3, r0, r3  ; r3 = cell id - grid
brn ANTDEATHISPERMANENT ; if negative, kill it
add r2, r2, r0  ; antword - grid size
brnzp ENDOFMOVE



SECTIONC
; if direction is 01, ant faces east
;; if (cellID % grid != grid -1)
;; then cellid++, else die
not r0, r4
add r0, r0, #1

add r5, r3, #0  ;    copy celll id to r5 to repeatedly subtract grid size
EASTMODLOOP
add r5, r5, r0  ;   cell id - grid
add r5, r5, #1  ; if this is 0, then r5 == grid - 1
brz ANTDEATHISPERMANENT
add r5, r5, #-1 ; but if not, undo it and re-loop
brn MOVEEAST    ; if negative, allowed to move east
                ; if equal to grid-1, ant is on eastern border and will die

BRNZP EASTMODLOOP

MOVEEAST
add r2, r2, #1  ; move east: CellID++
brnzp ENDOFMOVE

SECTIOND    ; first direction bit is 1
add r6, r6, #0  ; check if second bit is 0
brnp SECTIONF
; if it is 0, then direction is 10 = south
; if ant is on southern border, it dies
; if cellID >= grid^2-grid, then ant is on southern border

ld r0, N100
add r0, r0, r3  ; checking if grid size = 100
brz GRIDIS100
ld r0, GRIDSQ300HALF
add r3, r3, r0
add r3, r3, r0
add r3, r3, r0
add r3, r3, r0
brzp ANTDEATHISPERMANENT
add r2, r2, r4
brnzp ENDOFMOVE

GRIDIS100
ld r0, GRIDSQ100
add r3, r3, r0
brzp ANTDEATHISPERMANENT
add r2, r2, r4
brnzp ENDOFMOVE


SECTIONF
; direction bits are 11 = WEST
; if cellID % grid != 0, ant can go west, otherwise dead

add r6, r3, #0  ; copy cell id to r6
not r0, r4
add r0, r0, #1  ; r0 = -grid
WESTMODLOOP
add r6, r6, r0
brz ANTDEATHISPERMANENT
brn CANMOVEWEST
brp WESTMODLOOP

CANMOVEWEST
add r2, r2, #-1
brnzp ENDOFMOVE


ANTDEATHISPERMANENT
and r2, r2, #0
ld r7, LIVINGANTS
add r7, r7, #-1
st r7, LIVINGANTS

ENDOFMOVE
str r1, r2, #0  ;    double check this syntax
ld r2, MOVETEMP2
ld r3, MOVETEMP3
ld r5, MOVETEMP5
ld r6, MOVETEMP6
ld r7, MOVETEMP7
RET

N100 .fill #-100
GRIDSQ100 .fill #-9900
GRIDSQ300HALF .fill #-22425
MOVETEMP3 .fill #0
MOVETEMP2 .fill #0
MOVETEMP4 .fill #0
MOVETEMP5 .fill #0
MOVETEMP6 .fill #0
MOVETEMP7 .fill x0
IDMASK .fill x1FFF    ;   for extracting bits 12-0, the cell ID of the ant

; end of ANTSONTHEMOVE subroutine





FAKEXOR ; subroutine

; XOR of two registers
; INPUT r2, r4
; OUTPUT r6 = r2 XOR r4

; A in r4, not A in r5
; B in r2; not B in r6
; r4 XOR r2

st r5, XORTEMP5

not r6, r2
and r6, r6, r4  ; r6 = a & ~b
not r6, r6      ; r6 = ~(a & ~b)

not r5, r4      ; r5 = ~ a
and r5, r5, r2  ; r5 = ~a & b
not r5, r5      ; r5 = ~(~a & b)
and r6, r5, r6  ; r6 = ~(a & ~b) & ~(~a & b)
not r6, r6      ; r6 = ~( ~(a & ~b) & ~(~a & b) ) = a XOR b

ld r5, XORTEMP5

RET 

XORTEMP5 .fill #0


; SUBROUTINE
 FLIPPITY
; Takes a cell id and flips the bit in the grid, returns the original colour
; INPUT     r1: cell id
; LOCAL     r2: which bit to flip, then bitmask
;           r3: quotient, then address of byte to change
; OUTOUT    r5: original colour of cell id, before flipping. 1 if black, 0 if white.
;
; First, get byte (GRID + OFFSET)
; CELL ID / 16

st r4, FLIPTEMP4
st r5, FLIPTEMP5
st r6, FLIPTEMP6

and r3, r3, #0
add r2, r1, #0  ; copy cell id into r2

; loop to divide cellid by 16
FLIPLOOP
add r2, r2, #-16 ; cell id - 16
brn FLIPLOOPDONE    ; if negative, division done
add r3, r3, #1      ; if not negative, increment quotient and subtract again
BRNZP FLIPLOOP

FLIPLOOPDONE
add r2, r2, #8      ; add 16 back to negative number to get cellid % 16
add r2, r2, #8      ; this is which bit within the byte that the cell ID refers to

lea r4, GRID        ; starting address of GRID array
add r3, r3, r4      ; r3 = address of byte that will be changed = GRID base address + CELL ID / 16


lea r4, BM1         ; r4 = address of butmask array
add r4, r4, r2      ; r4 + which bit to flip = address of appropriate bitmask
ldr r2, r4, #0      ; r2 = bitmask to flip one bit

ldr r4, r3, #0      ; r4 = byte to be changed

and r0, r2, r4      ; indicates original colour of bit. 0 if white, non-zero if black

; A in r4, not A in r5
; B in r2; not B in r6
; r4 XOR r2
not r6, r2
and r6, r6, r4  ; r6 = a & ~b
not r6, r6      ; r6 = ~(a & ~b)

not r5, r4      ; r5 = ~ a
and r5, r5, r2  ; r5 = ~a & b
not r5, r5      ; r5 = ~(~a & b)
and r6, r5, r6  ; r6 = ~(a & ~b) & ~(~a & b)
not r6, r6      ; r6 = ~( ~(a & ~b) & ~(~a & b) ) = a XOR b


str r6, r3, #0

ld r4, FLIPTEMP4
ld r6, FLIPTEMP6

add r5, r0, #0  ; move colour of bit into r5 for output

ret
GRID .fill x8000
FLIPTEMP4 .fill #0
FLIPTEMP5 .fill #0
FLIPTEMP6 .fill #0

; bitmasks for flipping one bit
BM1 .fill x8000
BM2 .fill x4000
BM3 .fill x2000
BM4 .fill x1000
BM5 .fill x0800
BM6 .fill x0400
BM7 .fill x0200
BM8 .fill x0100
BM9 .fill x0080
BM10 .fill x0040
BM11 .fill x0020
BM12 .fill x0010
BM13 .fill x0008
BM14 .fill x0004
BM15 .fill x0002
BM16 .fill x0001

; END OF FLIPPITY SUBROUTINE





; SUBROUTINE
TAKEALEFTTURN
; turns the ant 90 degrees left

; INPUT R1: address in memory of ANT
; LOCAL R2: ant
;       R3: bitmask
;       R4: 3rdbit
;       R5: 2nd and 3rd bit
;       R6:
;       R7:
;       R0:

st r2, LEFTTURNTEMP2
st r3, LEFTTURNTEMP3
st r4, LEFTTURNTEMP4
st r6, LEFTTURNTEMP6
st r7, LEFTTURNTEMP7  ;  store r7, load before RET
ldr r2, r1, #0  ;  load ant into r2
ld r3, EAST
and r4, r2, r3 ; r4 = 3rdbit

ld r3, WEST
;and r5, r2, r3 ; r5 = 2nd and 3rd bits


add r4, r4, #0 ; check if 3rd bit is 0
brnp THIRDBIT1  ; If so, continue. If not, jump to next part.
; 3rd bit is 0, so XOR r2 ant-word with WEST bitmask, already in R3

BRNZP LEFTTURNEND

THIRDBIT1
; third bit is 1, so use EAST bitmask
ld r3, EAST

LEFTTURNEND

add r0, r4, #0  ; move r4 3rdbit into r0 temporarily
add r4, r3, #0  ; move r3 bitmask into r4 for the XOR subroutine
JSR FAKEXOR   ; r6 = r2 XOR r4
              ; flips the correct bit to turn left

add r3, r4, #0 ; moves r4 bitmask back into r3
add r4, r0, #0  ; moves r0 3rdbit back into r3

str r6, r1, #0  ; store tweaked ant-word with new direction back in memory

ld r2, LEFTTURNTEMP2
ld r3, LEFTTURNTEMP3
ld r4, LEFTTURNTEMP4
ld r6, LEFTTURNTEMP6
ld r7, LEFTTURNTEMP7
RET


WEST .fill X6000
EAST .fill x2000
NORTH .fill x0000
SOUTH .fill x4000

LEFTTURNTEMP2 .fill #0
LEFTTURNTEMP3 .fill #0
LEFTTURNTEMP4 .fill #0
LEFTTURNTEMP6 .fill #0
LEFTTURNTEMP7 .fill #0

; end of TAKEALEFTTURN subroutine



; SUBROUTINE
TAKEARIGHTTURN
; turns the ant 90 degrees right

; INPUT R1: address in memory of ANT
; LOCAL R2: ant
;       R3: bitmask
;       R4: 3rdbit
;   R5: 2nd and 3rd bit
;   R6:
;   R7:
;   R0:

st r2, RIGHTTURNTEMP2
st r3, RIGHTTURNTEMP3
st r4, RIGHTTURNTEMP4
st r6, RIGHTTURNTEMP6
st r7, RIGHTTURNTEMP7  ;  store r7, load before RET
ldr r2, r1, #0  ;  load ant into r2
ld r3, EAST
and r4, r2, r3 ; r4 = 3rdbit

;ld r3, WEST
;and r5, r2, r3 ; r5 = 2nd and 3rd bits


add r4, r4, #0 ; check if 3rd bit is 0
brnp THIRDBIT1RIGHT  ; If so, continue. If not, jump to next part.
; 3rd bit is 0, so XOR r2 ant-word with EAST bitmask
ld r3, EAST

BRNZP RIGHTTURNEND

THIRDBIT1RIGHT
; third bit is 1, so use WEST bitmask
ld r3, WEST

RIGHTTURNEND

add r0, r4, #0  ; move r4 3rdbit into r0 temporarily
add r4, r3, #0  ; move r3 bitmask into r4 for the XOR subroutine
JSR FAKEXOR   ; r6 = r2 XOR r4
              ; flips the correct bit to turn right

add r3, r4, #0 ; moves r4 bitmask back into r3
add r4, r0, #0  ; moves r0 3rdbit back into r3

str r6, r1, #0  ; store modified ant-word with new direction back in memory

ld r2, RIGHTTURNTEMP2
ld r3, RIGHTTURNTEMP3
ld r4, RIGHTTURNTEMP4
ld r6, RIGHTTURNTEMP6
ld r7, RIGHTTURNTEMP7
RET

RIGHTTURNTEMP2 .fill #0
RIGHTTURNTEMP3 .fill #0
RIGHTTURNTEMP4 .fill #0
RIGHTTURNTEMP6 .fill #0
RIGHTTURNTEMP7 .fill #0

; end of TAKEARIGHTTURN subroutine









; SUBROUTINE
ANTCOORDS
; INPUT     r2: index of ant
; OUTPUT    r1: x coordinate value
;           r3: y coordinate value
; "Enter x coordinates for ant #whatever"

st r4, COORD2

ld r0, NEWLINE
out
lea r0, ENTERXCOORDS
puts
ld r3, ASCIIPLUS
;add r0, r2, r3
;out
ld r0, NEWLINE
out


ld r5, ASCIIDIFF 
getc
out
add r4, r0, r5  ; r4 holds first digit of x

add r1, r4, r4  ; r1 = 2 * r4
add r1, r1, r1  ; r1 = 4 * r4
add r1, r1, r1  ; r1 = 8 * r4
add r1, r1, r4  ; r1 = 9 * r4
add r1, r1, r4  ; r1 = 10 * r4



getc
out
add r4, r0, r5  ; r4 holds 2nd digit of x
add r1, r1, r4  ; full value of x coordt
st r1, COORD1


; "enter y coords"
ld r0, NEWLINE
out
lea r0, ENTERYCOORDS
puts
ld r3, ASCIIPLUS
;add r0, r2, r3
;out
ld r0, NEWLINE
out

ld r5, ASCIIDIFF 
getc
out
add r4, r0, r5  ; r4 holds first digit of y

add r1, r4, r4  ; r1 = 2 * r4
add r1, r1, r1  ; r1 = 4 * r4
add r1, r1, r1  ; r1 = 8 * r4
add r1, r1, r4  ; r1 = 9 * r4
add r1, r1, r4  ; r1 = 10 * r4


getc
out
add r4, r0, r5  ; r4 holds 2nd digit of y
add r3, r1, r4  ; full value of y coord
ld r1, COORD1
ld r4, COORD2
RET


ENTERXCOORDS .STRINGZ "Enter x coordinates for ant "
ENTERYCOORDS .STRINGZ "Enter y coordinates for ant "
ASCIIDIFF .fill #-48
ASCIIPLUS .fill #48
COORD1 .fill #0
NEWLINE .fill #10
COORD2 .fill #0
COORD3 .fill #0

; END OF ANT_COORDINATES_SUBROUTINE




MAPPY
; Maps the coordinates of the ant
; Input:  R1: x coord
;  R3: y coord
;  R4: grid size
; Output: R5: Cell ID
; Cell ID = grid size * y coord + x coord

st r6, MAP1
st r7, MAP2

; multiply by 100
add R0, R3, R3 ; 2y
add R0, R0, R0 ; 4y
add R6, R0, R0 ; 8y
add R6, R6, R6 ; 16y
add R6, R6, R6 ; 32y
add R0, R0, R6 ; 36y
add R6, R6, R6 ; 64y
add R0, R0, R6 ; 100y

ld R7, N100a
add R7, R4, R7

brz GRID100a
add R0, R0, R0 ;200y
add R0, R0, R3 ;300y

GRID100a
Add R5, R0, R1  ; OUTPUT: R5 = grid*y + x


ld r6, MAP1
ld r7, MAP2
RET
N100a .fill #-100
MAP1 .fill #0
MAP2 .fill #0

; END OF MAPPY SUBROUTINE



.end
</lang>




=={{header|Liberty BASIC}}==
=={{header|Liberty BASIC}}==