-
Notifications
You must be signed in to change notification settings - Fork 0
/
parallel_snake.c
172 lines (142 loc) · 4.79 KB
/
parallel_snake.c
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include "main.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <omp.h>
#define LENGHT_ONE -2
//Redefine modulo so it work on negative numbers as expected
#define modulo(a,b) ((a)<0 ? (a+b)%b : (a)%b)
void run_simulation(int num_lines, int num_cols, int **world, int num_snakes,
struct snake *snakes, int step_count, char *file_name)
{
// TODO: Implement Parallel Snake simulation using the default (env. OMP_NUM_THREADS)
// number of threads.
//
// DO NOT include any I/O stuff here, but make sure that world and snakes
// parameters are updated as required for the final state.
int i;
int collision = 0;
int current_step;
//Compute Tails for Snakes
int done;
struct coord current;
char prevCell;
#pragma omp parallel for private(i,done,current,prevCell)
for (i = 0; i < num_snakes; i++) {
done = 0;
current = snakes[i].head;
prevCell = snakes[i].direction;
while (!done) {
//Check next Cell N
if (prevCell != 'N' && world[modulo(current.line - 1, num_lines)][current.col] == snakes[i].encoding) {
prevCell = 'S';
current.line = modulo(current.line - 1, num_lines);
}
//Check South Direction
else if (prevCell != 'S' && world[modulo(current.line + 1, num_lines)][current.col] == snakes[i].encoding) {
prevCell = 'N';
current.line = modulo(current.line + 1, num_lines);
}
//Check West direction
else if ( prevCell != 'V' && world[current.line][modulo(current.col - 1, num_cols)] == snakes[i].encoding) {
prevCell = 'E';
current.col = modulo(current.col - 1, num_cols);
}
//Check East Direction
else if (prevCell != 'E' && world[current.line][modulo(current.col + 1, num_cols)] == snakes[i].encoding) {
prevCell = 'V';
current.col = modulo(current.col + 1, num_cols);
}
//Tail Found
else {
done = 1;
snakes[i].tail = current;
}
}
}
//Execute Each Step
for (current_step = 0; current_step < step_count; current_step++) {
//Remove Tails
struct coord newTail;
#pragma omp parallel for private(i,newTail)
for (i = 0; i < num_snakes; i++) {
snakes[i].prevTail = snakes[i].tail;
world[snakes[i].tail.line][snakes[i].tail.col] = 0;
//Check North
if (world[modulo(snakes[i].tail.line - 1, num_cols)][snakes[i].tail.col] == snakes[i].encoding)
snakes[i].tail.line = modulo(snakes[i].tail.line - 1, num_cols);
//Check South
else if (world[modulo(snakes[i].tail.line + 1, num_lines)][snakes[i].tail.col] == snakes[i].encoding)
snakes[i].tail.line = modulo(snakes[i].tail.line + 1, num_lines);
//Check East
else if (world[snakes[i].tail.line][modulo(snakes[i].tail.col - 1, num_cols)] == snakes[i].encoding)
snakes[i].tail.col = modulo(snakes[i].tail.col - 1, num_cols);
//Check West
else if (world[snakes[i].tail.line][modulo(snakes[i].tail.col + 1, num_cols)] == snakes[i].encoding)
snakes[i].tail.col = modulo(snakes[i].tail.col + 1, num_cols);
//Check if Snakes tail coresponds with head
else
snakes[i].tail.line = LENGHT_ONE;
}
//Move Heads
#pragma omp parallel for private(i)
for (i = 0; i < num_snakes; i++) {
switch (snakes[i].direction) {
case 'N':
snakes[i].head.line = modulo(snakes[i].head.line - 1, num_lines);
break;
case 'S':
snakes[i].head.line = modulo(snakes[i].head.line + 1, num_lines);
break;
case 'E':
snakes[i].head.col = modulo(snakes[i].head.col + 1, num_cols);
break;
case 'V':
snakes[i].head.col = modulo(snakes[i].head.col - 1, num_cols);
break;
}
//Update tail if necesary
if (snakes[i].tail.line == LENGHT_ONE)
snakes[i].tail = snakes[i].head;
#pragma omp atomic
world[snakes[i].head.line][snakes[i].head.col] += snakes[i].encoding;
}
//Check Collision
#pragma omp parallel for private(i) shared(collision)
for (i = 0; i < num_snakes; i++) {
if (world[snakes[i].head.line][snakes[i].head.col] != snakes[i].encoding) {
#pragma omp atomic
collision++;
}
}
if (collision) {
//undoHead Write and HeadPosition
#pragma omp parallel for private(i)
for (i = 0; i < num_snakes; i++) {
#pragma omp atomic
world[snakes[i].head.line][snakes[i].head.col] -= snakes[i].encoding;
switch (snakes[i].direction)
{
case 'N':
snakes[i].head.line = modulo(snakes[i].head.line + 1, num_lines);
break;
case 'S':
snakes[i].head.line = modulo(snakes[i].head.line - 1, num_lines);
break;
case 'E':
snakes[i].head.col = modulo(snakes[i].head.col - 1, num_cols);
break;
case 'V':
snakes[i].head.col = modulo(snakes[i].head.col + 1, num_cols);
break;
}
}
//undoTails Delete
#pragma omp parallel for private(i)
for (i = 0; i < num_snakes; i++)
world[snakes[i].prevTail.line][snakes[i].prevTail.col] = snakes[i].encoding;
//End
current_step = step_count;
}
}
}