/* rubik.c */ /* started 23-Dec-89 */ /* Declarations for CBACK */ extern BPTR _Backstdout; /* std output when run in background */ long _BackGroundIO = 1; /* Flag to tell it we want to do I/O */ long _stack = 4000; /* Amount of stack space task needs */ char *_procname = "Rubik"; /* The name of the task to create */ long _priority = 0; /* The priority to run us at */ struct points point; /* holds posn.s of all points */ struct points start; struct one_square square[56]; /* 54 on cube plus 2 inter-planes */ struct coord *temp; struct Window *wnd1 = NULL; struct Window *wnd2 = NULL; struct Window *window; struct Screen *scr1 = NULL; struct Screen *scr2 = NULL; struct Screen *screen; struct IntuiMessage *msg = NULL; extern struct IntuiMessage *solve(); extern struct Gadget fastergadget,slowergadget; extern struct Gadget normalgadget,solvegadget,setupgadget; /* size is half the side length of a SMALL cube...1/6 of whole cube */ unsigned short size; short mode; int viewdist; short xcent,ycent; short alpha,beta,gamma,delta; unsigned short scaling; extern int clockwise (int); extern int whatsquare (int, int); extern int paints (int, int, int); extern short waiting_output; extern void init_squares(); extern void init_points(); extern void init_trig(); extern void cleanup(); extern void getwindow(); extern void roll (short); extern void yaw (short); extern void pitch (short); extern void twist (short, short); extern void draw_square(int); extern void showcube (short, short, short, short, short, short); extern void findangles (short *, short *, short *); extern void addpaints(); extern void removepaints(); extern void selectpen(int); extern void modcolours(int, int, int); extern void helpblurb(); extern void aboutblurb(); void swap (int i) { temp = square[i].corner[1]; square[i].corner[1] = square[i].corner[3]; square[i].corner[3] = temp; } void showit (short *alpha, short *beta, short *gamma) { ReplyMsg((struct Message *) msg); findangles(alpha,beta,gamma); showcube (*alpha,*beta,*gamma,0,0,0); } void select (short mode) /* pseudo mutual exclude */ { int i; for (i=0; i<3; i++) { SetDrMd (wnd1->RPort,JAM1); SetDrMd (wnd2->RPort,JAM1); if (i == mode) { SetAPen(wnd1->RPort,7); SetAPen(wnd2->RPort,7); } else { SetAPen(wnd1->RPort,0); SetAPen(wnd2->RPort,0); } RectFill (wnd1->RPort,198,114+12*i,252,124+12*i); RectFill (wnd2->RPort,198,114+12*i,252,124+12*i); SetDrMd (wnd1->RPort,COMPLEMENT); SetDrMd (wnd2->RPort,COMPLEMENT); switch (i) { case 0: Move(wnd1->RPort,202,122); Text(wnd1->RPort,"NORMAL",6); Move(wnd2->RPort,202,122); Text(wnd2->RPort,"NORMAL",6); break; case 1: Move(wnd1->RPort,206,134); Text(wnd1->RPort,"SOLVE",5); Move(wnd2->RPort,206,134); Text(wnd2->RPort,"SOLVE",5); break; case 2: Move(wnd1->RPort,206,146); Text(wnd1->RPort,"SETUP",5); Move(wnd2->RPort,206,146); Text(wnd2->RPort,"SETUP",5); break; } } SetDrMd (wnd1->RPort,JAM1); SetDrMd (wnd2->RPort,JAM1); } struct IntuiMessage *getmsg() { if ( (msg = (struct IntuiMessage *) GetMsg(wnd1->UserPort)) || (msg = (struct IntuiMessage *) GetMsg(wnd2->UserPort)) ) ; return (msg); } void showtwist (short i, short j) { showcube (alpha,beta,gamma,i,j,delta); } void _main (char *cmd) { int i,j; int pen; size = 2048; scaling = 7; viewdist = (2 << (scaling-3)) * size; init_trig(); getwindow(); init_squares(); init_points(); SetOPen(wnd1->RPort,0); SetOPen(wnd2->RPort,0); window = wnd1; screen = scr1; xcent = 96; ycent = 104; delta = 15; /* degrees of twist per frame */ alpha = 0; beta = 45; gamma = 30; /* make those squares that we can initialy see clockwise */ point = start; for (i=0; i<54; i++) { if (clockwise(i)) { if (i > 8) swap (i); } else /* anticlockwise */ { if (i < 9) swap (i); } } showcube (alpha,beta,gamma,0,0,0); select (mode = 0); waiting_output = 0; for (;;) /* forever */ { if (mode == 1) { msg = solve(); if (msg == NULL) select (mode = 0); } else msg = getmsg(); if (msg) { switch (msg->Class) { case CLOSEWINDOW: ReplyMsg((struct Message *) msg); cleanup(); Close (_Backstdout); exit(0L); break; case GADGETUP: switch (((struct Gadget *) msg->IAddress)->GadgetID) { case 1: roll (delta); showit (&alpha,&beta,&gamma); break; case 2: roll ((short) -delta); showit (&alpha,&beta,&gamma); break; case 3: yaw (delta); showit (&alpha,&beta,&gamma); break; case 4: yaw ((short) -delta); showit (&alpha,&beta,&gamma); break; case 5: pitch (delta); showit (&alpha,&beta,&gamma); break; case 6: pitch ((short) -delta); showit (&alpha,&beta,&gamma); break; case 7: /* front */ alpha = 0; beta = 45; gamma = 30; ReplyMsg((struct Message *) msg); showcube (alpha,beta,gamma,0,0,0); break; case 8: /* back */ alpha = 0; beta = -135; gamma = -30; ReplyMsg((struct Message *) msg); showcube (alpha,beta,gamma,0,0,0); break; case 9: /* faster */ ReplyMsg((struct Message *) msg); if (delta == 5) delta = 15; else if (delta == 15) delta = 30; else { delta = 45; OffGadget(&fastergadget,wnd1,NULL); OffGadget(&fastergadget,wnd2,NULL); } OnGadget(&slowergadget,wnd1,NULL); OnGadget(&slowergadget,wnd2,NULL); break; case 10: /* slower */ ReplyMsg((struct Message *) msg); if (delta == 45) delta = 30; else if (delta == 30) delta = 15; else { delta = 5; OffGadget(&slowergadget,wnd1,NULL); OffGadget(&slowergadget,wnd2,NULL); } OnGadget(&fastergadget,wnd1,NULL); OnGadget(&fastergadget,wnd2,NULL); break; case 11: /* help */ ReplyMsg((struct Message *) msg); helpblurb(); while ((msg = getmsg()) == NULL) Delay (1); ReplyMsg((struct Message *) msg); showcube (alpha,beta,gamma,0,0,0); break; case 12: /* about */ ReplyMsg((struct Message *) msg); aboutblurb(); while ((msg = getmsg()) == NULL) Delay (1); ReplyMsg((struct Message *) msg); showcube (alpha,beta,gamma,0,0,0); break; case 13: /* normal */ ReplyMsg((struct Message *) msg); if (mode == 2) removepaints(); select(mode = 0); SetDrMd(wnd1->RPort,JAM1); SetAPen(wnd1->RPort,0); RectFill(wnd1->RPort,190,150,317,197); ClipBlit ( wnd1->RPort,190,150, wnd2->RPort,190,150, 128,48, 0xc0 ); break; case 14: /* solve */ ReplyMsg((struct Message *) msg); if (mode == 2) removepaints(); select(mode = 1); break; case 15: /* setup */ if (mode != 2) { SetDrMd(wnd1->RPort,JAM1); SetAPen(wnd1->RPort,0); RectFill(wnd1->RPort,190,150,317,197); ClipBlit ( wnd1->RPort,190,150, wnd2->RPort,190,150, 128,48, 0xc0 ); addpaints(); pen = 1; } ReplyMsg((struct Message *) msg); select(mode = 2); break; case 16: /* redplus */ case 17: /* greenplus */ case 18: /* blueplus */ case 19: /* redminus */ case 20: /* greenminus */ case 21: /* blueminus */ i = ( ((struct Gadget *)msg->IAddress)->GadgetID ) -16; ReplyMsg((struct Message *) msg); if (mode == 2) { if (i > 2) modcolours(pen, i-3, -1); else modcolours(pen, i, +1); } break; case 22: case 23: case 24: case 25: case 26: case 27: /* choosing pen colour */ if (mode == 2) pen = ( ((struct Gadget *)msg->IAddress) ->GadgetID ) -21; ReplyMsg((struct Message *) msg); if (mode == 2) selectpen(pen); break; default: ReplyMsg((struct Message *) msg); break; } break; case MOUSEBUTTONS: if (msg->Code == SELECTDOWN || msg->Code == MENUDOWN) { if (mode == 0) { if ((i = whatsquare(msg->MouseX,msg->MouseY)) >=0) { /* make i = layer to twist, j = direction */ j = msg->Code == SELECTDOWN ? 1: -1; if ((i /= 9) == 1 || i == 2 || i == 4) j = -j; showtwist ((short) i,(short) j); waiting_output = 0; } } else if (mode == 2) { if ((i = paints(msg->MouseX,msg->MouseY,pen)) >=0) { (square[i]).colour = pen; waiting_output = 0; } } } ReplyMsg((struct Message *) msg); break; default: ReplyMsg((struct Message *) msg); break; } } else Delay (1); /* give other tasks a chance */ } }