home *** CD-ROM | disk | FTP | other *** search
- /* Next available MSG number is 20 */
-
- /*
- TOWER.C
- ¬⌐┼v (C) 1988-1992 Autodesk ñ╜Ñq
-
- Ñ╗│n┼ΘºK╢O¿╤▒z╢iªµÑ⌠ª≤Ñ╬│~╗▌¿D¬║½■¿⌐íB¡╫º∩ñ╬╡oªµ, ª²¼O░╚╜╨┐φ┤`ñU¡z
- ¡∞½h :
-
- 1) ñWªC¬║¬⌐┼v│qºi░╚╗▌ÑX▓{ªb¿Cñ@Ñ≈½■¿⌐∙╪íC
- 2) ¼█├÷¬║╗í⌐·ñσÑ≤ñ]Ñ▓╢╖⌐·╕ⁿ¬⌐┼v│qºiñ╬Ñ╗╢╡│\Ñi│qºiíC
-
- Ñ╗│n┼Θ╢╚┤ú¿╤º@¼░└│Ñ╬ñW¬║░╤ª╥, ª╙Ñ╝┴n⌐·⌐╬┴⌠ºtÑ⌠ª≤½O├╥; ╣∩⌐≤Ñ⌠ª≤»S«φ
- Ñ╬│~ñº╛A║┘⌐╩, ÑHñ╬░╙╖~╛P░Γ⌐╥┴⌠ºtÑX¿π¬║½O├╥, ªbª╣ñ@╖ºñ⌐ÑHº_╗{íC
-
-
-
- Tower of Hanoi in C
-
- Implemented by John Lynch December 1988
-
- This is basically a translation of tower.lsp written by
- Kelvin R. Throop.
-
- This file implements the Tower of Hanoi problem. It is as
- specified in the rules:
-
- 1. Only one disc may be moved at a time.
- 2. No disc may be placed on top of a smaller one.
-
- The only incompatibility with the original is that the universe
- will not come to an end when this function completes (however, if
- you run it with the specified number of discs, 64, the protons may
- decay before it's done).
-
- One defines the tower with the command TOWER, which asks for the
- number of discs. Scaling is automatic, as is clearing away of any
- previous execution. Once the tower is defined, the solution may
- be accomplished with the command SOLVE.
-
- The solution function, TRANSFER, is as given in Winston and Horn,
- "LISP", second edition, pp. 112-114.
-
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include "adslib.h"
-
-
- /* Local functions */
- static int loadfuncs _((void));
- static int dofun _((void));
- static int tower2 _((void));
- static int solve2 _((void));
- #ifdef __ZTC__
- static int movedisc _((int from, int to));
- static int transfer _((int from, int to, int spare, int n));
- #else
- static int movedisc _((short from, short to));
- static int transfer _((short from, short to, short spare, short n));
- #endif
-
-
- /* For convenience, make the global variables the same as in the LISP
- version */
-
- int nrings = 0, /* Number of rings */
- before = 0, /* Whether or not we have run before */
- armed = 0; /* Set if we are ready to solve */
-
- ads_real bthick = 1.0, /* Base thickness */
- rthick = 1.0, /* Ring thickness */
- smring = 1.5, /* Smallest ring */
- ringinc = 1.0, /* Ring size increment */
- postdia = 1.0, /* Post diameter */
- airspace = 0.1, /* Airspace */
- rspace = 1.1, /* Total ring space */
- postposx[3],
- postposy;
-
-
- /* Some of the common strings used to call AutoCAD's Command processor */
-
- char layer[] = /*MSG0*/"_.layer",
- vpoint[] = /*MSG0*/"_.vpoint",
- erase[] = /*MSG0*/"_.erase",
- new[] = /*MSG0*/"_new",
- set[] = /*MSG0*/"_set",
- base[] = /*MSG6*/"base",
- basetc[] = /*MSG7*/"base,1,2,3,4,5,6",
- color[] = /*MSG0*/"_color",
- elev[] = /*MSG0*/"_.elev",
- solid[] = /*MSG0*/"_.solid",
- zoom[] = /*MSG0*/"_.zoom",
- circle[] = /*MSG0*/"_.circle",
- origin[] = "0,0,0",
- oneoneone[] = "1,1,1",
- d[] = /*MSG0*/"_d",
- l[] = /*MSG0*/"_l",
- e[] = /*MSG0*/"_e",
- nullstring[] = "";
-
-
- /* The postlist structure is used to hold the disks */
- struct disk {
- struct disk *next;
- short layer;
- ads_real r;
- };
-
- struct postlist {
- struct disk *top;
- short count;
- };
-
- struct disk *disks;
- struct postlist postl[3];
-
-
- /* MAIN -- the main routine */
- void
- main(argc,argv)
- int argc; char *argv[];
- {
- int stat;
- short scode = RSRSLT;
-
- ads_init(argc, argv);
-
- for ( ;; ) {
-
- if ((stat = ads_link(scode)) < 0) {
- printf(/*MSG16*/"TOWER: Ñ╤ ads_link() ╢╟ª^¬║ñú¿╬¬¼║A = %d\n", stat);
- fflush(stdout);
- exit(1);
- }
-
- scode = RSRSLT; /* default return code */
-
- /* process the AutoLisp request */
- switch (stat) {
-
- case RQXLOAD: /* register our function names */
- scode = loadfuncs() ? -RSRSLT : -RSERR;
- break;
-
- case RQXUNLD: /* unload our functions */
- break;
-
- case RQSUBR: /* execute registered function */
- dofun();
- break;
-
- default:
- break;
- }
- }
- }
-
-
-
- /* LOADFUNCS -- Register (or define) external functions with AutoLISP */
- static int
- loadfuncs()
- {
- if (!ads_defun(/*MSG0*/"C:TOWER2", 0)) /* tower2 command has id 0 */
- return 0;
- if (!ads_defun(/*MSG0*/"C:SOLVE2", 1)) /* solve2 command has id 1 */
- return 0;
-
- ads_printf(/*MSG17*/"\
- ╣BÑ╬ tower2 ¿╙ªµíu▒╥⌐lív, ª╙ÑH solve2 ¿╙╕╤¿Míu╢≡ (tower)ív¬║░▌├D\n");
-
- return 1;
- }
-
- /* Execute registered functions here */
- static int
- dofun()
- {
- int id;
-
- /* Get the function id */
- if ((id = ads_getfuncode()) < 0)
- return 0;
-
- /* No arguments are passed as a part of C:XXX functions */
-
-
- switch (id) { /* Which function is being called */
- case 0:
- if (!tower2())
- return 0;
- break;
-
- case 1:
- if (!solve2())
- return 0;
- break;
- }
- return 1;
- }
-
- /* Handle setup of tower */
-
- static int
- tower2()
- {
- ads_real lring; /* largest ring diameter */
- int a, i;
- ads_real bwidth, blength; /* width and length of base */
- ads_real x, y, z, r;
- struct resbuf genrb;
- ads_point pt1, pt2, pt3, pt4;
-
- bthick = rthick = ringinc = postdia = 1.0;
- smring = 1.5;
- airspace = 0.1;
- rspace = 1.1;
-
-
- ads_getint(/*MSG18*/"┐ΘñJíu└⌠ (ring)ív╝╞╢q: ", &nrings);
-
- lring = smring + (nrings * ringinc);
-
- /* reset from possible previous run */
-
- postl[0].top = postl[1].top = postl[2].top = NULL;
- postl[0].count = postl[1].count = postl[2].count = 0;
-
-
- disks = (struct disk *) malloc ((nrings + 1) * (sizeof (struct disk)));
-
- rspace = rthick + airspace; /* Actual ring spacing */
-
- /* set up the appropriate environment variables */
- genrb.restype = RTSHORT;
- genrb.resval.rint = 0;
- ads_setvar(/*MSG0*/"blipmode", &genrb);
- ads_setvar(/*MSG0*/"cmdecho", &genrb);
- ads_setvar(/*MSG0*/"fillmode", &genrb);
-
-
- if (before) {
-
- ads_command(RTSTR, vpoint, RTSTR, origin, NULL);
-
- a = 1;
-
- while (a <= before) {
-
- ads_command(RTSTR, erase, RTSTR, l, RTSTR, nullstring, NULL);
-
- a++;
-
- }
-
- ads_command(RTSTR, layer, RTSTR, set, RTSTR, base, RTSTR,
- nullstring, NULL);
-
- } else {
-
- /* Note: this leave the command function "open" (non-terminated) */
- if (!ads_tblsearch (/*MSG0*/"layer", base, 1))
- ads_command(RTSTR, layer, RTSTR, new, RTSTR, basetc, RTSTR, color,
- RTSHORT, 7, RTSTR, base, NULL);
-
-
- a = 0;
-
- while (++a <= 6) {
-
- ads_command(RTSTR, color, RTSHORT, a, RTSHORT, a, NULL);
- }
-
- /* Set the current layer (command still "open") */
-
-
- ads_command(RTSTR, set, RTSTR, base, RTSTR, nullstring, NULL);
-
- }
-
- /* Draw the base */
-
- /* Command: "elev" 0.0 bthick */
-
- ads_command(RTSTR, elev, RTREAL, 0.0, RTREAL, bthick, NULL);
-
-
- bwidth = lring + 2 * postdia;
- blength = 3 * (postdia + lring) + postdia;
-
- ads_command(RTSTR, vpoint, RTSTR, origin, NULL);
-
- pt1[X] = pt1[Y] = 0.0;
- pt2[Y] = pt4[Y] = bwidth;
- pt3[X] = pt4[X] = blength;
- pt2[X] = pt3[Y] = 0.0;
-
- ads_command(RTSTR, solid, RTPOINT, pt1, RTPOINT, pt2, RTPOINT, pt3,
- RTPOINT, pt4, NULL);
-
-
- /* We must use ads_command(0) for ads_command(NULL) to be compatible */
- ads_command(0);
-
- ads_command(RTSTR, zoom, RTSTR, e, NULL);
-
- /* Draw the posts */
-
- /* Set the elevation through the command function */
- ads_command(RTSTR, elev, RTREAL, bthick, RTREAL,
- (nrings + 1) * rspace, NULL);
-
- x = postdia + lring;
- y = lring / 2 + postdia;
-
- postposx[0] = y;
- postposx[1] = y + x;
- postposx[2] = y + x + x;
-
- postposy = postdia + lring / 2;
-
- pt1[Y] = postposy;
-
- for (i = 0; i < 3; i++) {
- pt1[X] = postposx[i];
- ads_command(RTSTR, circle, RTPOINT, pt1, RTSTR, d, RTREAL,
- postdia, NULL);
- }
-
- bthick += airspace; /* Offset position of lowest ring */
-
- ads_command(RTSTR, vpoint, RTSTR, oneoneone, NULL);
-
-
- /* Draw the rings, placing them on post 1 initially */
-
- pt1[X] = y;
- pt1[Y] = postposy;
-
- a = 6;
- z = bthick;
- r = lring / 2;
- for (i = 1; i <= nrings; i++) {
-
- /* Command: "layer" "set" (l%6 + 1) "" */
- ads_command(RTSTR, layer, RTSTR, set, RTSHORT, a%6 + 1,
- RTSTR, nullstring, NULL);
-
- /* Command: "elev" z rthick */
-
- ads_command(RTSTR, elev, RTREAL, z, RTREAL, rthick, NULL);
-
- /* Command: "circle" (m postposy) r */
-
- pt1[Z] = z;
- ads_command(RTSTR, circle, RTPOINT, pt1, RTREAL, r, NULL);
-
-
- /* Hang it on the postlist */
- disks[i].layer = a%6 + 1;
- disks[i].r = r;
- disks[i].next = postl[0].top;
-
-
- postl[0].top = &disks[i];
- postl[0].count++;
-
- r -= ringinc / 2;
- z += rspace;
- a++;
-
-
- }
-
- before = nrings + 4;
-
- genrb.restype = RTSHORT;
- genrb.resval.rint = 0;
- ads_setvar(/*MSG0*/"cmdecho", &genrb);
-
- armed = TRUE;
- ads_retvoid();
-
- return TRUE;
-
- }
-
- /* Solve the tower problem. */
-
- static int
- solve2()
- {
- if (!armed) {
- ads_printf(/*MSG19*/"╕╤├Dñº½eÑ▓╢╖Ѳ░⌡ªµíutower2ív\n");
- return TRUE;
- } else
- armed = FALSE;
-
- transfer(1, 2, 3, nrings);
- ads_redraw(NULL, 0);
- ads_retvoid();
- return TRUE;
- }
-
- static int
- movedisc(from, to)
- short from, to;
- {
- struct disk *lfrom, *lto;
- ads_point pt;
-
- /* Get the current heads of the to and from lists */
- lfrom = postl[from - 1].top;
- lto = postl[to - 1].top;
-
- /* Remove this disk from the head of the from list */
- postl[from - 1].top = lfrom->next;
- postl[from - 1].count--;
-
- /* Command: "layer" "set" lfrom->layer "" */
-
- ads_command(RTSTR, layer, RTSTR, set, RTSHORT, lfrom->layer,
- RTSTR, nullstring, NULL);
-
- /* Command: "elev" b rthick */
-
- ads_command(RTSTR, elev, RTREAL, bthick + rspace * postl[from - 1].count,
- RTREAL, rthick, NULL);
-
-
- /* Command: "erase" postposx[from - 1], postposy+lfrom->r "" */
-
- pt[X] = postposx[from - 1];
- pt[Y] = postposy + lfrom->r;
- pt[Z] = bthick + rspace * postl[from-1].count;
-
- ads_command(RTSTR, erase, RTPOINT, pt, RTSTR, nullstring, NULL);
-
- /* Command: "elev" (bthick + postl[to-1]->count*rspace rthick */
-
- ads_command(RTSTR, elev, RTREAL, bthick + postl[to-1].count * rspace,
- RTREAL, rthick, NULL);
-
-
- /* Command: "circle" postpostx[to - 1],postposy lfrom->r */
-
- pt[X] = postposx[to - 1];
- pt[Y] = postposy;
- pt[Z] = bthick + postl[to-1].count * rspace;
-
- ads_command(RTSTR, circle, RTPOINT, pt, RTREAL, lfrom->r, NULL);
-
-
- /* Place the disk on the top of the to list */
- lfrom->next = lto;
- postl[to - 1].top = lfrom;
- postl[to - 1].count++;
-
- return TRUE;
- }
-
-
- static int
- transfer(from, to, spare, n)
- short from, to, spare, n;
- {
- if (n == 0)
- return TRUE;
- else if (n == 1)
- movedisc(from, to);
- else {
- transfer(from, spare, to, n - 1);
- movedisc(from, to);
- transfer(spare, to, from, n - 1);
- }
- return TRUE;
- }