-
Notifications
You must be signed in to change notification settings - Fork 3
/
turtle.c
138 lines (112 loc) · 2.84 KB
/
turtle.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
#include <libguile.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
static const int WIDTH = 10;
static const int HEIGHT = 10;
static FILE *start_gnuplot()
{
FILE *output;
// All data traveling through the pipe moves through the kernel
int pipes[2];
pid_t pid;
pipe(pipes);
pid = fork();
if (pid > 0)
{
/* Parent process closes up input side of pipe */
close(pipes[0]);
output = fdopen(pipes[1], "w");
fprintf(output, "set multiplot\n");
fprintf(output, "set parametric\n");
fprintf(output, "set xrange [-%d:%d]\n", WIDTH, WIDTH);
fprintf(output, "set yrange [-%d:%d]\n", HEIGHT, HEIGHT);
fprintf(output, "set size ratio -1\n");
fprintf(output, "unset xtics\n");
fprintf(output, "unset ytics\n");
fflush(output);
return output;
}
else if (pid == 0)
{
/*CHILD*/
/* Child process closes up output side of pipe */
close(pipes[1]);
dup2(pipes[0], STDIN_FILENO);
execlp("gnuplot", NULL);
return NULL; /* Not reached. */
}
else
{
perror("fork");
exit(1);
}
}
static FILE *global_output;
static void draw_line(FILE *output, double x1, double y1, double x2,
double y2)
{
fprintf(output, "plot [0:1] %f + %f * t, %f + %f * t notitle\n", x1, x2 - x1,
y1, y2 - y1);
fflush(output);
}
static double x, y;
static double direction;
static int pendown;
static SCM tortoise_reset()
{
x = y = 0.0;
direction = 0.0;
pendown = 1;
fprintf(global_output, "clear\n");
fflush(global_output);
return SCM_UNSPECIFIED;
}
static SCM tortoise_pendown()
{
SCM result = scm_from_bool(pendown);
pendown = 1;
return result;
}
static SCM tortoise_penup()
{
SCM result = scm_from_bool(pendown);
pendown = 0;
return result;
}
static SCM tortoise_turn(SCM degrees)
{
const double value = scm_to_double(degrees);
direction += M_PI / 180.0 * value;
return scm_from_double(direction * 180.0 / M_PI);
}
static SCM tortoise_move(SCM length)
{
const double value = scm_to_double(length);
double newX, newY;
newX = x + value * cos(direction);
newY = y + value * sin(direction);
if (pendown)
draw_line(global_output, x, y, newX, newY);
x = newX;
y = newY;
return scm_list_2(scm_from_double(x), scm_from_double(y));
}
static void *register_functions(void *data)
{
scm_c_define_gsubr("tortoise-reset", 0, 0, 0, &tortoise_reset);
scm_c_define_gsubr("tortoise-penup", 0, 0, 0, &tortoise_penup);
scm_c_define_gsubr("tortoise-pendown", 0, 0, 0, &tortoise_pendown);
scm_c_define_gsubr("tortoise-turn", 1, 0, 0, &tortoise_turn);
scm_c_define_gsubr("tortoise-move", 1, 0, 0, &tortoise_move);
return NULL;
}
int main(int argc, char *argv[])
{
global_output = start_gnuplot();
scm_with_guile(®ister_functions, NULL);
scm_shell(argc, argv);
return EXIT_SUCCESS;
}