2 * swar -- jerq space war
5 * ported to 9front on 31jul2021
12 #define NOBJ (1+2+6*2)
13 #define MSPEED (V/32) /* speed of missile relative to ship */
14 #define SZ 512 /* maximum scaled coordinate */
15 #define V 256 /* velocity scale factor */
16 #define G (V*11585) /* 11585 is SZ**(3./2.) */
22 #define SLEEP 40 /* ms per iteration */
23 #define TUBA (2000/SLEEP) /* iterations until born again */
24 #define HYTIME ((600+rand()%600)/SLEEP) /* iterations in hyperspace */
26 #include "deathstar.icon"
29 Rectangle starrect={0, 0, 16, 16};
31 #include "player0.icon"
34 Rectangle p0rect={0, 0, 44, 44};
36 #include "player1.icon"
39 Rectangle p1rect={0, 0, 44, 44};
41 #include "missile.icon"
44 Rectangle misrect={0, 0, 32, 32};
49 Rectangle boomrect={0, 0, 64, 64};
52 int vx, vy; /* scaled by V */
61 {0, 0, 0, 0, 0, SUN, 16},
62 { 300, 0, 0, 5*V, 8, ALIVE, 11, 0, 0, TUBA},
63 {-300, 0, 0, -5*V, 0, ALIVE, 11, 0, 0, TUBA},
64 {0, 0, 0, 0, 0, ALIVE, 8},
70 #define NORIENTATION 16
78 void kbdplayer(int c);
79 void hyper(struct obj *o);
80 void right(struct obj *o);
81 void left(struct obj *o);
82 void jerk(struct obj *o);
84 void fire(struct obj *o);
85 void initobj(struct obj *o);
86 void deathto(struct obj *o, int doboom);
87 void boom(struct obj *o);
88 void shards(struct obj *o);
89 void move(struct obj *o);
90 void blot(struct obj *o, int dwg);
91 void collide(struct obj *o, struct obj *p);
92 void newscore(struct obj *o, struct obj *p);
93 void drawscore(char *str, int sc, int where);
95 Image *initbitmap(char *bits[], Rectangle r);
97 #define sq(x) ((x)*(x))
98 #define muldiv(a, b, c) ((a)*(b)/(c))
115 draw(screen, screen->r, display->black, nil, ZP);
116 blot(ATT, ATT->orientation);
123 if(getwindow(display, Refnone) < 0)
125 xc=(screen->r.min.x+screen->r.max.x)/2;
126 yc=(screen->r.min.y+screen->r.max.y)/2;
127 size=min(screen->r.max.x-screen->r.min.x,
128 screen->r.max.y-screen->r.min.y)/2;
137 initdraw(nil,nil,nil);
138 einit(Ekeyboard|Emouse);
140 iobj[0].bp = stardwg = initbitmap(starbits, starrect);
141 iobj[1].bp = p0dwg = initbitmap(p0bits, p0rect);
142 iobj[2].bp = p1dwg = initbitmap(p1bits, p1rect);
143 iobj[3].bp = misdwg = initbitmap(misbits, misrect);
144 boomdwg = initbitmap(boombits, boomrect);
146 xc=(screen->r.min.x+screen->r.max.x)/2;
147 yc=(screen->r.min.y+screen->r.max.y)/2;
148 size=min(screen->r.max.x-screen->r.min.x,
149 screen->r.max.y-screen->r.min.y)/2;
154 for(;o!=&obj[NOBJ];o++)
159 for(o=obj;o!=&obj[NOBJ];o++){
163 for(p=o+1;p!=&obj[NOBJ];p++)
182 if((o==P0 || o==P1) && --o->timer==0)
191 flushimage(display, 1);
192 while(ecanmouse()) emouse();
193 if(ecankbd()) kbdplayer(ekbd());
197 void kbdplayer(int c){
199 case 'k': left(P0); break;
200 case 'o': jerk(P0); break;
201 case ';': right(P0); break;
202 case 'l': fire(P0); break;
204 case ',': hyper(P0); break;
205 case 'a': left(P1); break;
206 case 'w': jerk(P1); break;
207 case 'd': right(P1); break;
208 case 's': fire(P1); break;
210 case 'x': hyper(P1); break;
211 case 'Q': exits(""); break;
214 void hyper(struct obj *o){
221 void right(struct obj *o){
222 if(++o->orientation==NORIENTATION)
225 void left(struct obj *o){
226 if(--o->orientation<0)
227 o->orientation=NORIENTATION-1;
229 void jerk(struct obj *o){
230 o->vx+=dv[o->orientation].x/2;
231 o->vy+=dv[o->orientation].y/2;
237 if(x>=32768L*(32768L/4))
238 return(2*isqrt(x/4)); /* avoid overflow */
239 for(s=2, u=4;u<x;s+=s, u*=4);
240 while((u=((x+s*s)/s)>>1)<s)
244 void fire(struct obj *o){
249 for(m=o+2;m<&obj[NOBJ];m+=2)
253 vl=isqrt(sq(o->vx)+sq(o->vy));
256 vx=muldiv(vl, dv[o->orientation].x, V);
257 vy=muldiv(vl, dv[o->orientation].y, V);
258 m->x=o->x+muldiv(vx, (o->diameter+m->diameter), vl);
259 m->y=o->y+muldiv(vy, (o->diameter+m->diameter), vl);
260 m->vx=o->vx+MSPEED*dv[o->orientation].x;
261 m->vy=o->vy+MSPEED*dv[o->orientation].y;
262 blot(m, m->orientation);
266 void initobj(struct obj *o){
267 *o=(o>P1)?iobj[P1-obj+1]:iobj[o-obj];
269 blot(o, o->orientation);
271 void deathto(struct obj *o, int doboom){
277 void boom(struct obj *o){
280 o->diameter=boomdwg->r.max.x/4;
281 blot(o, o->orientation=0);
283 void shards(struct obj *o){
284 if(++o->orientation==16){
290 void move(struct obj *o){
293 if(o->state==DEAD || o->state==SUN)
295 r32=o->x*o->x+o->y*o->y;
297 r32*=isqrt(r32); /* pow(r, 3./2.) */
306 if(o>P1 && o->wrapped){
311 if(x<-SZ) x+=2*SZ; else x-=2*SZ;
315 if(o>P1 && o->wrapped)
317 if(y<-SZ) y+=2*SZ; else y-=2*SZ;
324 blot(o, o->orientation);
328 #define rescale(x) muldiv(x, size, SZ)
331 blot(struct obj *o, int dwg)
334 int dx = dwg % 4*o->diameter, dy = dwg / 4*o->diameter;
336 p = Pt(rescale(o->x)+xc-o->diameter/2, rescale(o->y)+yc-o->diameter/2);
338 draw(screen, rectaddpt(Rect(dx,dy,dx+o->diameter,dy+o->diameter),p), o->bp, nil, Pt(dx, dy));
343 collide(struct obj *o, struct obj *p)
347 if(o->state!=HYPER && p->state!=HYPER
348 && sq(rescale(o->x-p->x))+sq(rescale(o->y-p->y))<
349 sq(o->diameter+p->diameter)/4){
351 if(doneboom=o->state==ALIVE)
354 deathto(p, !doneboom || (o==P0 && p==P1));
359 newscore(struct obj *o, struct obj *p)
372 drawscore(char *str, int sc, int where)
392 s = screen->r.min.x + 20;
394 s = (screen->r.min.x + screen->r.max.x - stringwidth(font, p))/2;
396 s = screen->r.max.x - stringwidth(font, p) - 20;
398 draw(screen, Rpt(Pt(s, screen->r.min.y+5),Pt(s+stringwidth(font, p), screen->r.min.y+5+font->height)), display->black, nil, ZP);
399 string(screen, Pt(s, screen->r.min.y+5), display->white, ZP, font, p);
405 drawscore(" MCI", score[0], 0);
406 drawscore(" AT&T", score[2], 1);
407 drawscore(" SPRINT", score[1], 2);
411 initbitmap(char *bits[], Rectangle r)
415 Image *b=allocimage(display, r, screen->chan, 0, DTransparent);
418 sysfatal("allocimage: %r");
420 for(p.y = r.min.y; p.y != r.max.y; p.y++){
421 bit = bits[p.y-r.min.y];
422 for(p.x = r.min.x; p.x != r.max.x; p.x++){
426 draw(b, Rpt(p,addpt(p,Pt(1,1))), display->white, nil, ZP);