File Coverage

lib/Game/RaycastFOV.xs
Criterion Covered Total %
statement 90 90 100.0
branch 91 134 67.9
condition n/a
subroutine n/a
pod n/a
total 181 224 80.8


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6              
7             #include "ppport.h"
8              
9             #include "math.h"
10              
11             #define CALLTWOUP \
12             ENTER; \
13             SAVETMPS; \
14             PUSHMARK(SP); \
15             EXTEND(SP, 2)
16             #define TWOUPDONE \
17             FREETMPS; \
18             LEAVE
19             #define CIRCLECB(x, y) \
20             do { \
21             key = Perl_form(aTHX_ "%d,%d", x, y); \
22             len = strlen(key); \
23             if(!hv_exists(seen, key, len)) { \
24             hv_store(seen, key, len, &PL_sv_yes, 0); \
25             PUSHMARK(SP); \
26             EXTEND(SP, 2); \
27             mPUSHs(newSViv(x)); \
28             mPUSHs(newSViv(y)); \
29             PUTBACK; \
30             call_sv(callback, G_DISCARD); \
31             SPAGAIN; \
32             } \
33             } while (0)
34              
35             MODULE = Game::RaycastFOV PACKAGE = Game::RaycastFOV
36             PROTOTYPES: ENABLE
37              
38             void
39             bypair (callback, ...)
40             SV *callback;
41             PREINIT:
42             int answer, i;
43             SV *x, *y;
44             PROTOTYPE: &@
45             PPCODE:
46 3 100         if (!(items & 1)) croak("uneven number of arguments");
47             dSP;
48 4 100         for (i = 1; i < items; i += 2) {
49 3           x = ST(i);
50 3           y = ST(i + 1);
51 3 50         CALLTWOUP;
    50          
52 3           PUSHs(x);
53 3           PUSHs(y);
54 3           PUTBACK;
55 3           call_sv(callback, G_SCALAR);
56 3           SPAGAIN;
57 3 50         answer = POPi;
58 3 50         TWOUPDONE;
59 3 100         if (answer == -1) break;
60             }
61              
62             void
63             bypairall (callback, ...)
64             SV *callback;
65             PREINIT:
66             int i;
67             SV *x, *y;
68             PROTOTYPE: &@
69             PPCODE:
70 5 100         if (!(items & 1)) croak("uneven number of arguments");
71             dSP;
72 47 100         for (i = 1; i < items; i += 2) {
73 43           x = ST(i);
74 43           y = ST(i + 1);
75 43 50         CALLTWOUP;
    50          
76 43           PUSHs(x);
77 43           PUSHs(y);
78 43           PUTBACK;
79 43           call_sv(callback, G_DISCARD);
80 43           SPAGAIN;
81 43 50         TWOUPDONE;
82             }
83              
84             void
85             circle (callback, int x0, int y0, int radius)
86             SV *callback;
87             PREINIT:
88             char *key;
89             int f, ddF_x, ddF_y, x, y;
90             HV* seen;
91             STRLEN len;
92             PROTOTYPE: &$$$
93             PPCODE:
94 4           dSP;
95 4           ENTER;
96 4           SAVETMPS;
97 4           sv_2mortal((SV *)(seen = newHV()));
98 4           f = 1 - radius;
99             ddF_x = 0;
100 4           ddF_y = -2 * radius;
101             x = 0;
102             y = radius;
103 4 50         CIRCLECB(x0, y0 + radius);
    50          
    50          
104 4 50         CIRCLECB(x0, y0 - radius);
    50          
    50          
105 4 50         CIRCLECB(x0 + radius, y0);
    50          
    50          
106 4 50         CIRCLECB(x0 - radius, y0);
    50          
    50          
107 9 100         while (x < y) {
108 5 100         if (f >= 0) {
109 4           y--;
110 4           ddF_y += 2;
111 4           f += ddF_y;
112             }
113 5           x++;
114 5           ddF_x += 2;
115 5           f += ddF_x + 1;
116 5 100         CIRCLECB(x0 + x, y0 + y);
    50          
    50          
117 5 100         CIRCLECB(x0 - x, y0 + y);
    50          
    50          
118 5 100         CIRCLECB(x0 + x, y0 - y);
    50          
    50          
119 5 100         CIRCLECB(x0 - x, y0 - y);
    50          
    50          
120 5 100         CIRCLECB(x0 + y, y0 + x);
    50          
    50          
121 5 100         CIRCLECB(x0 - y, y0 + x);
    50          
    50          
122 5 100         CIRCLECB(x0 + y, y0 - x);
    50          
    50          
123 5 100         CIRCLECB(x0 - y, y0 - x);
    50          
    50          
124             }
125 4 50         FREETMPS;
126 4           LEAVE;
127              
128             void
129             line (callback, int x0, int y0, int x1, int y1)
130             SV *callback;
131             PREINIT:
132             int answer, dx, dy, err, e2, sx, sy;
133             PROTOTYPE: &$$$$
134             PPCODE:
135 43           dSP;
136 43           dx = abs(x1 - x0);
137 43           dy = abs(y1 - y0);
138 43 100         sx = x0 < x1 ? 1 : -1;
139 43 100         sy = y0 < y1 ? 1 : -1;
140 104 100         err = (dx > dy ? dx : -dy) / 2;
141             while (1) {
142 104 50         CALLTWOUP;
    50          
143 104           mPUSHs(newSViv(x0));
144 104           mPUSHs(newSViv(y0));
145 104           PUTBACK;
146 104           call_sv(callback, G_SCALAR);
147 104           SPAGAIN;
148 104 50         answer = POPi;
149 104 50         TWOUPDONE;
150 104 100         if (answer == -1 || (x0 == x1 && y0 == y1)) break;
    100          
151             e2 = err;
152 61 100         if (e2 > -dx) {
153 41           err -= dy;
154 41           x0 += sx;
155             }
156 61 100         if (e2 < dy) {
157 40           err += dx;
158 40           y0 += sy;
159             }
160             }
161              
162             void
163             sub_circle (callback, long x0, long y0, unsigned long radius, double swing, double angle, double max_angle)
164             SV *callback;
165             PREINIT:
166             char *key;
167             long newx, newy;
168             HV* seen;
169             STRLEN len;
170             PROTOTYPE: &$$$$$$
171             PPCODE:
172 3           dSP;
173 3           sv_2mortal((SV *)(seen = newHV()));
174 648 100         while (angle < max_angle) {
175 645           newx = x0 + lrint(radius * cos(angle));
176 645           newy = y0 + lrint(radius * sin(angle));
177 645           key = Perl_form(aTHX_ "%ld,%ld", newx, newy);
178 645           len = strlen(key);
179 645 100         if(!hv_exists(seen, key, len)) {
180 24           hv_store(seen, key, len, &PL_sv_yes, 0);
181 24 50         CALLTWOUP;
    50          
182 24           mPUSHs(newSViv(newx));
183 24           mPUSHs(newSViv(newy));
184 24           PUTBACK;
185 24           call_sv(callback, G_DISCARD);
186 24           SPAGAIN;
187 24 50         TWOUPDONE;
188             }
189 645           angle += swing;
190             }