|
|
1.1 root 1: /*% mcc -g % -o swar
2: * swar -- jerq space war
3: * td&rob 84.01.01
4: */
5: #include <jerq.h>
6: #undef min
7: Bitmap ToBitmap();
8:
9: int xc, yc;
10: #define NOBJ (1+2+6*2)
11: #define MSPEED (V/32) /* speed of missile relative to ship */
12: #define SZ 512 /* maximum scaled coordinate */
13: #define V 256 /* velocity scale factor */
14: #define G ((long)V*11585) /* 11585 is SZ**(3./2.) */
15: #define ALIVE 1
16: #define DEAD 2
17: #define SUN 3
18: #define BOOM 4
19: #define HYPER 5
20: #define SLEEP 2 /* ticks per iteration */
21: #define TUBA (120/SLEEP) /* ticks until born again */
22: #define HYTIME ((40+rand()%40)/SLEEP)
23: short starbits[]={
24: #include "deathstar.icon"
25: };
26: Bitmap stardwg;
27: short p0bits[]={
28: #include "player0.icon"
29: };
30: Bitmap p0dwg;
31: short p1bits[]={
32: #include "player1.icon"
33: };
34: Bitmap p1dwg;
35: short misbits[]={
36: #include "missile.icon"
37: };
38: Bitmap misdwg;
39: short boombits[]={
40: #include "boom.icon"
41: };
42: Bitmap boomdwg;
43: struct obj{
44: int x, y;
45: long vx, vy; /* scaled by V */
46: int orientation;
47: int state;
48: int diameter;
49: Bitmap *bp;
50: int curdwg;
51: #define wrapped timer
52: int timer;
53: }obj[NOBJ], iobj[]={
54: {0, 0, 0, 0, 0, SUN, 16, &stardwg},
55: { 300, 0, 0, 5*V, 8, ALIVE, 11, &p0dwg, 0, TUBA},
56: {-300, 0, 0, -5*V, 0, ALIVE, 11, &p1dwg, 0, TUBA},
57: {0, 0, 0, 0, 0, ALIVE, 8, &misdwg},
58: };
59: #define ATT (&obj[0])
60: #define P0 (&obj[1])
61: #define P1 (&obj[2])
62: int score[3];
63: #define NORIENTATION 16
64: struct dv{
65: long x, y;
66: }dv[NORIENTATION]={
67: #include "accel.h"
68: };
69: int xc, yc, size;
70: #define sq(x) ((long)(x)*(long)(x))
71: int min(a, b){return(a<b?a:b);}
72: long lmin(a, b)long a,b;{return(a<b?a:b);}
73: int abs(a){return(a<0?-a:a);}
74: main(argc,argv){
75: register i;
76: register struct obj *o, *p;
77: request(KBD);
78: initdisplay(argc,argv);
79: stardwg=ToBitmap((char *)starbits, 4, 0, 0, 16, 16);
80: p0dwg=ToBitmap((char *)p0bits, 8, 0, 0, 44, 44);
81: p1dwg=ToBitmap((char *)p1bits, 8, 0, 0, 44, 44);
82: misdwg=ToBitmap((char *)misbits, 4, 0, 0, 32, 32);
83: boomdwg=ToBitmap((char *)boombits, 8, 0, 0, 64, 64);
84: xc=(Drect.origin.x+Drect.corner.x)/2;
85: yc=(Drect.origin.y+Drect.corner.y)/2;
86: size=min(Drect.corner.x-Drect.origin.x,
87: Drect.corner.y-Drect.origin.y)/2;
88: rectf (&display, Drect, F_XOR);
89: for(o=obj;o<=P1;o++)
90: initobj(o);
91: for(;o!=&obj[NOBJ];o++)
92: o->state=DEAD;
93: doscore();
94: for(;;){
95: for(o=obj;o!=&obj[NOBJ];o++){
96: switch(o->state){
97: case ALIVE:
98: case SUN:
99: for(p=o+1;p!=&obj[NOBJ];p++)
100: if(p->state!=DEAD)
101: collide(o, p);
102: if(o>P1)
103: left(o);
104: move(o);
105: break;
106: case HYPER:
107: if(--o->timer==0){
108: blot(o, o->curdwg);
109: o->state=ALIVE;
110: if(rand()%4==0){
111: deathto(o, 1);
112: newscore(ATT, o);
113: }
114: }else
115: move(o);
116: break;
117: case DEAD:
118: if((o==P0 || o==P1) && --o->timer==0)
119: initobj(o);
120: break;
121: case BOOM:
122: shards(o);
123: move(o);
124: break;
125: }
126: }
127: if(own()&KBD)
128: kbdplayer(kbdchar());
129: sleep(SLEEP);
130: }
131: }
132: kbdplayer(c){
133: switch(c){
134: case ';': left(P0); break;
135: case 'o': jerk(P0); break;
136: case 'k': right(P0); break;
137: case 'l': fire(P0); break;
138: case '/':
139: case '.': hyper(P0); break;
140: case 'a': left(P1); break;
141: case 'w': jerk(P1); break;
142: case 'd': right(P1); break;
143: case 's': fire(P1); break;
144: case 'z':
145: case 'x': hyper(P1); break;
146: case 'Q': exit(); break;
147: }
148: }
149: hyper(o)
150: register struct obj *o;
151: {
152: if(o->state!=ALIVE)
153: return;
154: o->state=HYPER;
155: o->timer=HYTIME;
156: blot(o, o->curdwg);
157: }
158: right(o)
159: register struct obj *o;
160: {
161: if(++o->orientation==NORIENTATION)
162: o->orientation=0;
163: }
164: left(o)
165: register struct obj *o;
166: {
167: if(--o->orientation<0)
168: o->orientation=NORIENTATION-1;
169: }
170: jerk(o)
171: register struct obj *o;
172: {
173: o->vx+=dv[o->orientation].x/2;
174: o->vy+=dv[o->orientation].y/2;
175: }
176: long isqrt(x)
177: register long x;
178: {
179: register long s, u;
180: if(x<=0)
181: return(0);
182: if(x>=32768L*(32768L/4))
183: return(2*isqrt(x/4)); /* avoid overflow */
184: for(s=2, u=4;u<x;s+=s, u*=4);
185: while((u=((x+s*s)/s)>>1)<s)
186: s=u;
187: return(s);
188: }
189: fire(o)
190: register struct obj *o;
191: {
192: register struct obj *m;
193: register vx, vy, vl;
194:
195: if(o->state!=ALIVE)
196: return;
197: for(m=o+2;m<&obj[NOBJ];m+=2)
198: if(m->state==DEAD){
199: initobj(m);
200: m->state=ALIVE;
201: vl=isqrt(sq(o->vx)+sq(o->vy));
202: if(vl==0)
203: vl=V;
204: vx=muldiv(vl, dv[o->orientation].x, V);
205: vy=muldiv(vl, dv[o->orientation].y, V);
206: m->x=o->x+muldiv(vx, (o->diameter+m->diameter), vl);
207: m->y=o->y+muldiv(vy, (o->diameter+m->diameter), vl);
208: m->vx=o->vx+MSPEED*dv[o->orientation].x;
209: m->vy=o->vy+MSPEED*dv[o->orientation].y;
210: blot(m, m->orientation);
211: return;
212: }
213: }
214: initobj(o)
215: register struct obj *o;
216: {
217: *o=(o>P1)?iobj[P1-obj+1]:iobj[o-obj];
218: if(o<=P1)
219: blot(o, o->orientation);
220: }
221: deathto(o, doboom)
222: register struct obj *o;
223: {
224: o->state=DEAD;
225: blot(o, o->curdwg);
226: if(doboom)
227: boom(o);
228: }
229: boom(o)
230: register struct obj *o;
231: {
232: o->state=BOOM;
233: o->bp= &boomdwg;
234: o->diameter=boomdwg.rect.corner.x/4;
235: blot(o, o->orientation=0);
236: }
237: shards(o)
238: register struct obj *o;
239: {
240: if(++o->orientation==16){
241: blot(o, o->curdwg);
242: o->state=DEAD;
243: o->timer=TUBA;
244: }
245: }
246: move(o)
247: register struct obj *o;
248: {
249: register long r32;
250: register x, y;
251: if(o->state==DEAD || o->state==SUN)
252: return;
253: r32=(long)o->x*o->x+(long)o->y*o->y;
254: if(r32!=0){
255: r32*=isqrt(r32); /* pow(r, 3./2.) */
256: if(r32!=0){
257: o->vx-=G*o->x/r32;
258: o->vy-=G*o->y/r32;
259: }
260: }
261: x=o->x+o->vx/V;
262: y=o->y+o->vy/V;
263: if(x<-SZ || SZ<x){
264: if(o>P1 && o->wrapped){
265: Death:
266: deathto(o, 0);
267: return;
268: }
269: if(x<-SZ) x+=2*SZ; else x-=2*SZ;
270: o->wrapped++;
271: }
272: if(y<-SZ || SZ<y){
273: if(o>P1 && o->wrapped)
274: goto Death;
275: if(y<-SZ) y+=2*SZ; else y-=2*SZ;
276: o->wrapped++;
277: }
278: if(o->state!=HYPER)
279: blot(o, o->curdwg);
280: o->x=x, o->y=y;
281: if(o->state!=HYPER)
282: blot(o, o->orientation);
283: }
284: #define BLOTSIZE 5
285: #define rescale(x) muldiv(x, size, SZ)
286: blot(o, dwg)
287: register struct obj *o;
288: {
289: register dx=dwg%4*o->diameter, dy=dwg/4*o->diameter;
290: bitblt(o->bp, Rect(dx, dy, dx+o->diameter, dy+o->diameter),
291: &display, Pt(rescale(o->x)+xc-o->diameter/2,
292: rescale(o->y)+yc-o->diameter/2), F_XOR);
293: o->curdwg=dwg;
294: }
295: collide(o, p)
296: register struct obj *o, *p;
297: {
298: register doneboom;
299: /* o<p always */
300: if(o->state!=HYPER && p->state!=HYPER
301: && sq(rescale(o->x-p->x))+sq(rescale(o->y-p->y))<
302: sq(o->diameter+p->diameter)/4){
303: newscore(o, p);
304: if(doneboom=o->state==ALIVE)
305: deathto(o, 1);
306: if(p->state==ALIVE)
307: deathto(p, !doneboom || (o==P0 && p==P1));
308: }
309: }
310: newscore(o, p)
311: register struct obj *o, *p;
312: {
313: doscore();
314: /* o<p always */
315: score[2]++;
316: if(o==P0 || p==P0)
317: score[1]++;
318: if(o==P1 || p==P1)
319: score[0]++;
320: doscore();
321: }
322: drawscore(str, sc, where)
323: char *str;
324: {
325: static char buf[16];
326: register char *p=buf+6;
327: register s;
328: do; while(*p++= *str++);
329: p=buf+6;
330: s=abs(sc);
331: do{
332: *--p=s%10+'0';
333: s/=10;
334: }while(s); /*mcc bug */
335: if(sc<0)
336: *--p='-';
337: if(where==2)
338: s=Drect.origin.x;
339: else if(where==1)
340: s=(Drect.origin.x+Drect.corner.x-strwidth(&defont, p))/2;
341: else
342: s=Drect.corner.x-strwidth(&defont, p);
343: string(&defont, p, &display, Pt(s, Drect.origin.y+5), F_XOR);
344: }
345: doscore()
346: {
347: drawscore(" MCI", score[0], 0);
348: drawscore(" AT&T", score[2], 1);
349: drawscore(" SPRINT", score[1], 2);
350: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.