-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathspheres.c
195 lines (171 loc) · 6.33 KB
/
spheres.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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation
rmsphere(x,y) Function to delete a sphere of annihilation from list
sphboom(x,y) Function to perform the effects of a sphere detonation
movsphere() Function to look for and move spheres of annihilation
*/
#include <stdlib.h>
#include "larncons.h"
#include "larndata.h"
#include "larnfunc.h"
static void sphboom(int x, int y);
/*
* newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation
* int x,y,dir,lifetime;
*
* Enter with the coordinates of the sphere in x,y
* the direction (0-8 diroffx format) in dir, and the lifespan of the
* sphere in lifetime (in turns)
* Returns the number of spheres currently in existence
*/
int newsphere(int x, int y, int dir, int life)
{
int m;
struct sphere *sp;
if (((sp=(struct sphere *)malloc(sizeof(struct sphere)))) == 0)
return(c[SPHCAST]); /* can't malloc, therefore failure */
if (dir>=9) dir=0; /* no movement if direction not found */
if (level==0) vxy(&x,&y); /* don't go out of bounds */
else
{
if (x<1) x=1; if (x>=MAXX-1) x=MAXX-2;
if (y<1) y=1; if (y>=MAXY-1) y=MAXY-2;
}
if ((m=mitem[x][y]) >= DEMONLORD+4) /* demons dispel spheres */
{
show1cell(x,y); /* show the demon (ha ha) */
cursors(); lprintf("\nThe %s dispels the sphere!",monster[m].name);
rmsphere(x,y); /* remove any spheres that are here */
return(c[SPHCAST]);
}
if (m==DISENCHANTRESS) /* disenchantress cancels spheres */
{
cursors(); lprintf("\nThe %s causes cancellation of the sphere!",monster[m].name);
boom: sphboom(x,y); /* blow up stuff around sphere */
rmsphere(x,y); /* remove any spheres that are here */
return(c[SPHCAST]);
}
if (c[CANCELLATION]) /* cancellation cancels spheres */
{
cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
goto boom;
}
if (item[x][y]==OANNIHILATION) /* collision of spheres detonates spheres */
{
cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!");
rmsphere(x,y);
goto boom;
}
if (playerx==x && playery==y) /* collision of sphere and player! */
{
cursors();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
rmsphere(x,y); /* remove any spheres that are here */
nap(4000); died(258);
}
item[x][y]=OANNIHILATION; mitem[x][y]=0; know[x][y]=1;
show1cell(x,y); /* show the new sphere */
sp->x=x; sp->y=y; sp->lev=level; sp->dir=dir; sp->lifetime=life; sp->p=0;
if (spheres==0) spheres=sp; /* if first node in the sphere list */
else /* add sphere to beginning of linked list */
{
sp->p = spheres; spheres = sp;
}
return(++c[SPHCAST]); /* one more sphere in the world */
}
/*
* rmsphere(x,y) Function to delete a sphere of annihilation from list
* int x,y;
*
* Enter with the coordinates of the sphere (on current level)
* Returns the number of spheres currently in existence
*/
int rmsphere(int x, int y)
{
struct sphere *sp, *sp2 = 0;
for (sp=spheres; sp; sp2=sp,sp=sp->p)
if (level==sp->lev) /* is sphere on this level? */
if ((x==sp->x) && (y==sp->y)) /* locate sphere at this location */
{
item[x][y]=mitem[x][y]=0; know[x][y]=1;
show1cell(x,y); /* show the now missing sphere */
--c[SPHCAST];
if (sp==spheres) { sp2=sp; spheres=sp->p; free((char*)sp2); }
else
{ sp2->p = sp->p; free((char*)sp); }
break;
}
/* return number of spheres in the world */
return c[SPHCAST];
}
/*
* sphboom(x,y) Function to perform the effects of a sphere detonation
* int x,y;
*
* Enter with the coordinates of the blast, Returns no value
*/
static void sphboom(int x, int y)
{
int i, j;
if (c[HOLDMONST]) c[HOLDMONST]=1;
if (c[CANCELLATION]) c[CANCELLATION]=1;
for (j=max(1,x-2); j<min(x+3,MAXX-1); j++)
for (i=max(1,y-2); i<min(y+3,MAXY-1); i++)
{
item[j][i]=mitem[j][i]=0;
show1cell(j,i);
if (playerx==j && playery==i)
{
cursors();
lprcat("\nYou were too close to the sphere!");
nap(3000);
died(283); /* player killed in explosion */
}
}
}
/*
* movsphere() Function to look for and move spheres of annihilation
*
* This function works on the sphere linked list, first duplicating the list
* (the act of moving changes the list), then processing each sphere in order
* to move it. They eat anything in their way, including stairs, volcanic
* shafts, potions, etc, except for upper level demons, who can dispel
* spheres.
* No value is returned.
*/
#define SPHMAX 20 /* maximum number of spheres movsphere can handle */
void movsphere(void)
{
int x, y, dir, len;
struct sphere *sp, *sp2;
struct sphere sph[SPHMAX];
/* first duplicate sphere list */
for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */
if (sp2->lev == level) /* only if this level */
{
sph[x] = *sp2; sph[x++].p = 0; /* copy the struct */
if (x>1) sph[x-2].p = &sph[x-1]; /* link pointers */
}
if (x) sp= sph; /* if any spheres, point to them */
else return; /* no spheres */
for (sp=sph; sp; sp=sp->p) /* look through sphere list */
{
x = sp->x; y = sp->y;
if (item[x][y]!=OANNIHILATION) continue; /* not really there */
if (--(sp->lifetime) < 0) /* has sphere run out of gas? */
{
rmsphere(x,y); /* delete sphere */
continue;
}
switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */
{
case 1:
case 2: /* change direction to a random one */
sp->dir = rnd(8);
default: /* move in normal direction */
dir = sp->dir; len = sp->lifetime;
rmsphere(x,y);
newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
};
}
}