~mikelma/oktac

oktac/examples/game-of-life/main.ok -rw-r--r-- 2.9 KiB
79afb735 — mikelma basic lambda function support 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use ffi

const WORLD_SIZE:   u64 = 42
const SLEEP_MILLIS: u64 = 200
const SEED:         u64 = 10
const GRID_LEN:     u64 = WORLD_SIZE * WORLD_SIZE 

fun main() {
    srand(SEED);

    let world = gen_world();
    let aux = gen_world();

    random_init(&world);

    copy_world(&world, &aux);

    printf(@cstr("%c[1;1H%c[2J"), 27, 27); # clear terminal
    print_world(&world);

    loop {
        usleep(1000*SLEEP_MILLIS);

        for let i:u64=0; i<WORLD_SIZE; i=i+1 {
            for let j:u64=0; j<WORLD_SIZE; j=j+1 {
                let count = count_neighbours(&world, i, j);

                if count < 2 || count > 3 {
                    set_cell(&aux, i, j, 0);

                } elif count == 3 {
                    set_cell(&aux, i, j, 1);
                }
            }
        }

        copy_world(&aux, &world);

        printf(@cstr("%c[1;1H%c[2J"), 27, 27); # clear terminal
        print_world(&world);
    }
}

fun gen_world(): [i8] {
    let world = @slice(
        calloc(GRID_LEN, @sizeof(i8)), 
        GRID_LEN
    );
    ret world;
}

fun count_neighbours(world: &[i8], i: u64, j: u64): i8 {
    let count = 0i8;

    # upper neighbor
    if i > 0 {
        count = count + get_cell(world, i-1, j);

        # upper-left neighbor
        if j > 0 {
            count = count + get_cell(world, i-1, j-1);
        }
        # upper-right neighbor
        if j < WORLD_SIZE - 1 {
            count = count + get_cell(world, i-1, j+1);
        }
    }

    # lower neighbor
    if i < WORLD_SIZE - 1 {
        count = count + get_cell(world, i+1, j);

        # lower-left neighbor
        if j > 0 {
            count = count + get_cell(world, i+1, j-1);
        }
        # lowe-right neighbor
        if j < WORLD_SIZE - 1 {
            count = count + get_cell(world, i+1, j+1);
        }
    }

    # left neighbor
    if j > 0 {
        count = count + get_cell(world, i, j-1);
    }

    # right neighbor
    if j < WORLD_SIZE - 1 {
        count = count + get_cell(world, i, j+1);
    }

    ret count;
}

fun get_cell(world: &[i8], i: u64, j: u64): i8 {
    ret *world[i*WORLD_SIZE + j];
}

fun set_cell(world: &[i8], i: u64, j: u64, value: i8) {
    *world[i*WORLD_SIZE + j] = value;
}


fun print_world(world: &[i8]) {
    for let i:u64=0; i<WORLD_SIZE; i=i+1 {
        for let j:u64=0; j<WORLD_SIZE; j=j+1 {
            # alive cell
            if get_cell(world, i, j) == 1 {
                printf(@cstr("█"));

            # dead cell =/
            } else {
                printf(@cstr(" "));
            }
        }
        printf(@cstr("\n"));
    }
}

fun random_init(world: &[i8]) {
    for let i=0u64; i<WORLD_SIZE; i=i+1 {
        for let j=0u64; j<WORLD_SIZE; j=j+1 {
            *world[i*WORLD_SIZE+j] = rand() & 1;
        }
    }
}

fun copy_world(from: &[i8], to: &[i8]) {
    for let i=0u64; i<WORLD_SIZE; i=i+1 {
        for let j=0u64; j<WORLD_SIZE; j=j+1 {
            set_cell(to, i, j, get_cell(from, i, j));
        }
    }
}