Skip to content

Commit 78a8692

Browse files
committed
Functionnal Langton Ant
1 parent 2f9ff09 commit 78a8692

File tree

5 files changed

+128
-122
lines changed

5 files changed

+128
-122
lines changed

www/index.html

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ <h1>Langton's ant</h1>
2626
</div>
2727
</div>
2828
</div>
29-
<table id="field">
30-
31-
</table>
29+
<div id="field"></div>
3230
<script src=""></script>
3331
</section>
3432
<footer>

www/scripts/Ant.js

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,20 @@
22
const UP = true;
33
const DOWN = false;
44

5-
const RIGHT = 1;
6-
const LEFT = -1;
7-
8-
let dir = {
9-
NORTH: [-1, 0],
10-
EAST: [0, 1],
11-
SOUTH: [1, 0],
12-
WEST: [0, ]
5+
const dir = {
6+
NORTH: [0, -1],
7+
EAST: [1, 0],
8+
SOUTH: [0, 1],
9+
WEST: [-1, 0]
1310
}
1411

15-
let cardinals = [dir.NORTH, dir.EAST, dir.SOUTH, dir.WEST];
12+
const cardinals = [dir.NORTH, dir.EAST, dir.SOUTH, dir.WEST];
1613

1714
class Ant {
18-
constructor ({x, y}, field) {
15+
constructor ({x, y}, table) {
1916
this.pos = [x, y];
2017
this.dir = this.randomHeading();
21-
this.field = field;
18+
this.table = table;
2219
}
2320

2421
randomHeading () {
@@ -27,22 +24,38 @@ class Ant {
2724
return heading;
2825
}
2926

30-
updateHeading (cell_state) {
31-
let current_heading = this.dir;
32-
if (cell_state == UP) {
33-
this.rotate(LEFT);
27+
updateHeading () {
28+
let cell = this.underCell;
29+
if (this.isUp(cell)) {
30+
this.rotate("LEFT");
3431
} else {
35-
this.rotate(RIGHT);
32+
this.rotate("RIGHT");
3633
}
3734
}
3835

3936
rotate (direction) {
40-
let cardinal_step = direction;
41-
let former_cardinal = this.dir;
42-
let former_index = cardinals.indexOf(former_cardinal);
43-
let new_index = (former_index + cardinal_step) % cardinals.length;
44-
let new_cardinal = cardinals[new_index];
45-
this.dir = new_cardinal;
37+
// console.log(direction);
38+
if (direction == "RIGHT") {
39+
if (this.dir == dir.NORTH) {
40+
this.dir = dir.EAST;
41+
} else if (this.dir == dir.EAST) {
42+
this.dir = dir.SOUTH;
43+
} else if (this.dir == dir.SOUTH) {
44+
this.dir = dir.WEST;
45+
} else if (this.dir == dir.WEST) {
46+
this.dir = dir.NORTH;
47+
}
48+
} else if (direction == "LEFT") {
49+
if (this.dir == dir.NORTH) {
50+
this.dir = dir.WEST;
51+
} else if (this.dir == dir.WEST) {
52+
this.dir = dir.SOUTH;
53+
} else if (this.dir == dir.SOUTH) {
54+
this.dir = dir.EAST;
55+
} else if (this.dir == dir.EAST) {
56+
this.dir = dir.NORTH;
57+
}
58+
}
4659
}
4760

4861
forward () {
@@ -53,18 +66,43 @@ class Ant {
5366
}
5467

5568
update () {
56-
let pos = {...this.pos};
57-
let cell = this.field[this.pos.y][this.pos.x];
58-
this.updateHeading(cell);
69+
this.updateHeading();
5970
this.forward();
60-
this.field[pos.y][pos.x] = switchCellState(cell);
71+
}
72+
73+
draw () {
74+
// Get previous cell associated with and id
75+
let prev_cell = document.getElementById('ant');
76+
if (prev_cell != undefined) {
77+
// Remove the obsolete attribute
78+
prev_cell.removeAttribute('id');
79+
}
80+
let current_cell = this.underCell;
81+
// console.log(current_cell);
82+
current_cell.id = "ant";
83+
this.switchCellState(current_cell);
84+
}
85+
86+
isOut(table_width, table_height) {
87+
return this.pos.x < 0 || this.pos.y < 0 || this.pos.x > table_width || this.pos.y > table_height;
88+
}
89+
90+
resetPos({x, y}) {
91+
this.pos = [x, y];
6192
}
6293

63-
isOut(field_width, field_height) {
64-
return this.pos.x < 0 || this.pos.y < 0 || this.pos.x > field_width || this.pos.y > field_height;
94+
get underCell() {
95+
let i = this.pos[0];
96+
let j = this.pos[1];
97+
let cell = this.table.childNodes[i].childNodes[j];
98+
return cell;
6599
}
66-
}
67100

68-
function switchCellState(cell_state) {
69-
return cell_state == UP ? DOWN : UP;
101+
switchCellState(cell) {
102+
cell.classList.toggle('up');
103+
}
104+
105+
isUp(cell) {
106+
return cell.classList.contains('up');
107+
}
70108
}

www/scripts/action.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,11 @@ reset_button.addEventListener('click', function () {
2525
ant_stop();
2626
ant_reset();
2727
});
28+
29+
30+
let speed_slider = document.getElementById('speed');
31+
32+
speed_slider.addEventListener('click', function() {
33+
let speed_value = speed_slider.value;
34+
setUpSpeed(speed_value);
35+
});

www/scripts/app.js

Lines changed: 50 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,87 @@
11
let resolution = 10 // px per case of the field
22

3-
let default_cell_state = DOWN;
3+
let interval = undefined;
44

55
let size2cell = (size, resolution) => Math.floor(size / resolution);
66

7-
const table_size = {
8-
width: size2cell(window_size.innerWidth, resolution),
9-
height: size2cell(window_size.innerHeight, resolution)
10-
}
11-
12-
let field_table = createFieldTable(resolution, {width: table_size.width, height: table_size.height});
13-
14-
const initial_pos = {
15-
x: Math.floor(field_table[0].length / 2),
16-
y: Math.floor(field_table.length / 2)
7+
let table_size = {
8+
width: size2cell(window.innerWidth, resolution),
9+
height: size2cell(window.innerHeight, resolution)
1710
}
1811

19-
let field_element = document.getElementById('field');
20-
21-
let interval = undefined;
12+
let initial_pos = {
13+
x: Math.floor(table_size.width / 2),
14+
y: Math.floor(table_size.height / 2)
15+
};
2216

23-
field_element = createHtmlTable(field_element, field_table);
17+
let field = document.getElementById('field');
2418

25-
let myAnt = new Ant({x: initial_pos.x, y: initial_pos.y}, field_element);
19+
createTable(field, {
20+
n_col: table_size.width,
21+
n_row: table_size.height
22+
});
2623

27-
drawAnt({x: myAnt.pos.x, y: myAnt.pos.y}, field_element);
28-
29-
function createFieldTable(resolution, {n_col: width, n_row: height} ) {
30-
let table = []
24+
function createTable(parent, { n_col, n_row }) {
25+
let table = document.createElement('table');
3126
for (let j = 0; j < n_row; j++) {
32-
let row = [];
27+
let row = document.createElement('tr');
3328
for (let i = 0; i < n_col; i++) {
34-
let cell = default_cell_state;
35-
row.push(cell);
29+
let cell = document.createElement('td');
30+
row.appendChild(cell);
3631
}
37-
table.push(row);
32+
table.appendChild(row);
3833
}
39-
return table;
34+
parent.appendChild(table);
4035
}
4136

42-
function createHtmlTable(field_element, field_table) {
43-
for (let i = 0; i < field_table.length; i++) {
44-
let row_element = document.createElement('tr');
45-
for (let j = 0; j < field_table[i].length; j++) {
46-
let cell_element = document.createElement('td');
47-
cell_element.classList.add('cell');
48-
row_element.appendChild(cell_element);
37+
let table = field.firstChild;
38+
39+
function forEachCell(table, action) {
40+
let rows = table.childNodes;
41+
for (row of rows) {
42+
let cells = row.childNodes;
43+
for (cell of cells) {
44+
action(cell);
4945
}
50-
field_element.appendChild(row_element);
5146
}
5247
}
5348

54-
function UpdateHtmlTable(field_element, table_field) {
55-
let j = 0;
56-
const max_j = field_table.length;
57-
const max_i = field_table[0].length;
58-
field_element.childNodes.forEach(tr => {
59-
let i = 0;
60-
tr.childNodes.forEach(td => {
61-
if (i < max_i && j < max_j) {
62-
// console.log(`cell at (${i}, ${j})`);
63-
let cell = table_field[j][i];
64-
if (isUp(cell))
65-
{
66-
if (! td.classList.contains('up')) {
67-
td.classList.add('up');
68-
}
69-
} else {
70-
td.classList.remove('up');
71-
}
72-
i++;
73-
} else {
74-
return;
75-
}
76-
});
77-
j++;
78-
});
79-
}
49+
forEachCell(table, (cell) => cell.classList.add('cell'));
8050

81-
function isUp(cell) {
82-
return cell == UP;
83-
}
51+
let myAnt = new Ant({x: initial_pos.x, y: initial_pos.y}, table);
8452

85-
function drawAnt({x, y}, field_element) {
86-
87-
let previous_ant = document.getElementById('ant');
88-
if (previous_ant != null) {
89-
// clear previous ant
90-
previous_ant.removeAttribute('id');
91-
}
92-
let next_ant_cell = field_element.childNodes[y].childNodes[x];
93-
// draw new ant
94-
next_ant_cell.id = 'ant';
95-
}
53+
myAnt.draw();
9654

97-
function nextState() {
55+
function next() {
9856
myAnt.update();
99-
drawAnt(myAnt.pos, field_element);
100-
UpdateHtmlTable(field_element, field_table);
101-
if (myAnt.isOut(field_table[0].length, field_table.length)) {
102-
window.clearInterval(loop);
103-
}
57+
myAnt.draw();
10458
}
10559

10660
function ant_start() {
107-
interval = setInterval(nextState, 10);
61+
let dt = 1 / document.getElementById('speed').value;
62+
interval = setInterval(next, 100);
10863
}
10964

110-
11165
function ant_stop() {
11266
clearInterval(interval);
11367
}
11468

115-
11669
function ant_next() {
117-
nextState();
70+
next();
71+
if (myAnt.isOut(table_size.width, table_size.height)) {
72+
ant_stop();
73+
}
11874
}
11975

12076
function ant_reset() {
121-
field_table = createFieldTable(resolution, size.x, size.y);
122-
myAnt = new Ant(initial_pos.x, initial_pos.y, field_table);
123-
UpdateHtmlTable(field_element, field_table);
124-
drawAnt(myAnt, field_element);
125-
}
77+
forEachCell(table, (cell) => cell.classList.remove('up'));
78+
myAnt.resetPos({x: initial_pos.x, y: initial_pos.y});
79+
myAnt.draw();
80+
}
81+
82+
83+
function setUpSpeed(speed_value) {
84+
let dt = 1 / speed_value * 1000;
85+
clearInterval(interval);
86+
setInterval(ant_next, dt);
87+
}

www/scripts/config.js

Whitespace-only changes.

0 commit comments

Comments
 (0)