kyle@xanth.UUCP (03/12/87)
# After reading the last thirty or so articles requesting the sources # for various games I said to myself, "Self! Wouldn't it be a novel # and wonderful thing if someone were to actually post SOURCES to this # newsgroup?!" # # Here is a program that does the Towers of Hanoi simulation or lets # you attempt to solve it yourself. No, its not UltraRogue but it's still # fun to watch. It will run as is on BSD systems, and ought to run with # very little tweaking under System V. # # kyle jones, odu computer science # ARPA: kyle@xanth.cs.odu.edu CSNET: kyle@odu.csnet # UUCP: kyle@xanth.uucp # # This is a shell archive. # Run the file through sh to extract its contents. # shar: Shell Archiver # Run the following text with /bin/sh to create: # Makefile # hanoi.6 # hanoi.c # hanoi.h # init.c # main.c # move.c # pegs.c # This archive created: Thu Mar 12 00:45:15 1987 echo shar: extracting Makefile '(197 characters)' sed 's/^XX//' << \SHAR_EOF > Makefile XXCFLAGS = -O XX XXhanoi: main.o hanoi.o move.o init.o pegs.o XX cc -O -o hanoi main.o hanoi.o move.o init.o pegs.o -lcurses -ltermlib XX XXmain.o hanoi.o move.o init.o : hanoi.h XX XXclean: XX rm -f *.o hanoi core SHAR_EOF if test 197 -ne "`wc -c Makefile`" then echo shar: error transmitting Makefile '(should have been 197 characters)' fi echo shar: extracting hanoi.6 '(886 characters)' sed 's/^XX//' << \SHAR_EOF > hanoi.6 XX.TH HANOI ODU XX.SH NAME XXhanoi \- Tower of Hanoi simulation XX.SH SYNOPSIS XXhanoi [-v | -a] number XX.SH DESCRIPTION XX.I Hanoi XXdoes a visual simulation of the Tower of Hanoi problem, using XX.I curses(3X). XXThe program will solve the puzzle itself if given the XX.I -a XXoption, otherwise it sets up the puzzle and prompts you for disc moves until XXyou solve the puzzle. XX.I Number XXshould be the number of discs that you want to be in the puzzle. XXIf the XX.I -v XXoption is given XX.I hanoi XXwill tell you what move you just made and display a count of moves you've made XXso far. XX.PP XXThe puzzle consists of a number of different sized discs stacked XXon one of three pegs. The object is to move all the discs (one at a time) XXfrom this peg to one of the other two pegs, XX\fIwithout ever placing a larger disc on top on a smaller one.\fR XX.SH AUTHOR XXKyle Jones, Old Dominion University Computer Science, Norfolk VA. SHAR_EOF if test 886 -ne "`wc -c hanoi.6`" then echo shar: error transmitting hanoi.6 '(should have been 886 characters)' fi echo shar: extracting hanoi.c '(235 characters)' sed 's/^XX//' << \SHAR_EOF > hanoi.c XXhanoi(nrings, from, to) XXint nrings, from, to; XX XX{ XX int other; XX XX if (nrings == 1) XX movering(from, to); XX else { XX other = 3 - (from + to); XX hanoi(nrings-1, from, other); XX movering(from, to); XX hanoi(nrings-1, other, to); XX } XX return; XX} SHAR_EOF if test 235 -ne "`wc -c hanoi.c`" then echo shar: error transmitting hanoi.c '(should have been 235 characters)' fi echo shar: extracting hanoi.h '(81 characters)' sed 's/^XX//' << \SHAR_EOF > hanoi.h XX#define MAX_RINGS 9 XX XX#define PEG0_COL 20 XX#define PEG1_COL 40 XX#define PEG2_COL 60 SHAR_EOF if test 81 -ne "`wc -c hanoi.h`" then echo shar: error transmitting hanoi.h '(should have been 81 characters)' fi echo shar: extracting init.c '(1138 characters)' sed 's/^XX//' << \SHAR_EOF > init.c XX#include <curses.h> XX#include <signal.h> XX#include "hanoi.h" XX XXextern char *ring[]; XXint goodbye(); XX XXinit_curses() XX XX{ XX if (initscr() == ERR) { XX fprintf(stderr, "Sorry, but your terminal isn't powerful "); XX fprintf(stderr, "to run Hanoi.\nIt lacks some important "); XX fprintf(stderr, "features."); XX exit(1); XX } XX signal(SIGINT, goodbye); XX return; XX} XX XXinit_pegs(nrings) XXint nrings; XX XX{ XX for (; nrings > 0; nrings--) XX push(0, nrings); XX return; XX} XX XXdraw_slab() XX XX{ XX move(LINES-2, 0); XX addstr(" ================[1]=================[2]=================[3]==============="); XX move(LINES-3, 0); XX addstr(" =================|===================|===================|================"); XX refresh(); XX return; XX} XX XXdraw_pegs() XX XX{ XX int y; XX XX for (y=LINES-MAX_RINGS-4; y < LINES-3; y++) { XX mvaddch(y, PEG0_COL, '|'); XX mvaddch(y, PEG1_COL, '|'); XX mvaddch(y, PEG2_COL, '|'); XX } XX refresh(); XX} XX XXdraw_rings(nrings) XXint nrings; XX XX{ XX int y, x; XX XX y = LINES - 4; XX for (; nrings > 0; nrings--, y--) { XX x = PEG0_COL - nrings; XX mvaddstr(y, x, ring[nrings]); XX } XX refresh(); XX return; XX} XX XXgoodbye() XX XX{ XX move(LINES-1, 0); XX clrtoeol(); XX refresh(); XX endwin(); XX exit(0); XX} SHAR_EOF if test 1138 -ne "`wc -c init.c`" then echo shar: error transmitting init.c '(should have been 1138 characters)' fi echo shar: extracting main.c '(2145 characters)' sed 's/^XX//' << \SHAR_EOF > main.c XX#include <curses.h> XX#include "hanoi.h" XX XXint verbose, automatic; XX XXmain(c, v) XXint c; XXchar **v; XX XX{ XX int nrings; XX XX if (c < 2 || c > 3) { XX fprintf(stderr,"usage: %s [-v|-a] <1-%d>\n", v[0], MAX_RINGS); XX exit(1); XX } XX if (strcmp(v[1], "-v") == 0) XX verbose++; XX else if (strcmp(v[1], "-a") == 0) XX automatic++; XX nrings = atoi(v[c-1]); XX if (!nrings || nrings > MAX_RINGS) { XX fprintf(stderr, "usage: %s [-v] <1-%d>\n", v[0], MAX_RINGS); XX exit(1); XX } XX XX init_curses(); XX init_pegs(nrings); XX draw_slab(); XX draw_pegs(); XX draw_rings(nrings); XX if (automatic) { XX hanoi(nrings, 0, 1); XX goodbye(); XX } XX Interactive(); XX} XX XXInteractive() XX XX{ XX int from, to, fromdisk, todisk; XX XX crmode(); XX noecho(); XX verbose = 1; XX for (;;) { XX from = GetNumber("Move disk from peg: "); XX if (peg_height(from-1) == 0) { XX Message("No disk on that peg..."); XX sleep(2); XX continue; XX } XX fromdisk = pop(from-1); XX push(from-1, fromdisk); XX Light(from-1); XX to = GetNumber("To peg: "); XX if (peg_height(to-1) != 0) { XX todisk = pop(to-1); XX push(to-1, todisk); XX if (fromdisk > todisk) { XX Douse(from-1); XX Message("Cannot move larger disk onto smaller one."); XX sleep(2); XX continue; XX } XX } XX Message(""); XX movering(from-1, to-1); XX if (!peg_height(0) && (!peg_height(1) || !peg_height(2))) { XX switch (peg_height(to-1)) { XX case 1: XX Message("Phhhhft!"); break; XX case 2: XX Message("Ha!"); break; XX case 3: XX Message("Well, it's about time!"); break; XX case 4: XX Message("Not bad... for a human."); break; XX case 5: XX Message("Finally!"); break; XX case 6: XX Message("Good, now be gone!"); break; XX default: XX Message("It was pure luck!"); break; XX } XX getch(); XX goodbye(0); XX } XX } XX} XX XXint XXGetNumber(prompt) XXchar *prompt; XX XX{ XX char c; XX XX move(LINES-1, 0); XX clrtoeol(); XX addstr(prompt); XX refresh(); XX for (;;) { XX c = getch(); XX if (c == 'q' || c == 'Q') XX goodbye(); XX if (c > '0' && c < '4') XX break; XX } XX return (int) (c - '0'); XX} XX XXMessage(string) XXchar *string; XX XX{ XX move(LINES-1, 0); XX clrtoeol(); XX move(LINES-1, 0); XX standout(); XX addstr(string); XX standend(); XX refresh(); XX return; XX} SHAR_EOF if test 2145 -ne "`wc -c main.c`" then echo shar: error transmitting main.c '(should have been 2145 characters)' fi echo shar: extracting move.c '(2530 characters)' sed 's/^XX//' << \SHAR_EOF > move.c XX#include <curses.h> XX#include "hanoi.h" XX XXextern int verbose; XX XXchar *ring[] = { XX "0", XX "111", XX "22222", XX "3333333", XX "444444444", XX "55555555555", XX "6666666666666", XX "777777777777777", XX "88888888888888888", XX "9999999999999999999" XX}; XX XXstatic char blotter[] = " | "; XX XXint pegcol[3] = { PEG0_COL, PEG1_COL, PEG2_COL }; XX XXmovering(from, to) XXint from, to; XX XX{ XX static int moveno = 0; XX int ringno, fromheight, toheight, y, x, moveleft, destx, dx, ringsize; XX int pegtop; XX char blotbuf[MAX_RINGS*2+2]; XX XX pegtop = LINES - MAX_RINGS - 5; XX XX fromheight = peg_height(from); XX XX /* XX * Get the number of the ring we gotta move XX */ XX ringno = pop(from); XX XX toheight = peg_height(to); XX XX if (verbose) { XX moveno++; XX move(pegtop - 3, pegcol[1] - 2); XX printw("%3d", moveno); XX move(pegtop - 2, pegcol[1] - 7); XX printw("disc %d to peg %d", ringno, to+1); XX refresh(); XX } XX XX /* XX * From the ring number compute the size of the ring. XX */ XX ringsize = 2 * ringno + 1; XX XX /* XX * Center the ring on the peg. XX */ XX x = pegcol[from] - ringno; XX XX /* XX * Lift ring from peg XX */ XX strncpy(blotbuf, blotter+(MAX_RINGS-ringno), ringsize); XX blotbuf[ringsize] = '\0'; XX for (y=LINES-fromheight-3; y > pegtop; y--) { XX mvaddstr(y, x, blotbuf); XX mvaddstr(y-1, x, ring[ringno]); XX refresh(); XX } XX XX /* XX * Decide which direction we have to shift the ring. XX */ XX destx = pegcol[to] - ringno; XX moveleft = (x > destx ? 1 : 0); XX dx = (moveleft ? -1 : 1); XX move(pegtop, 0); XX XX /* XX * Now shift the ring over to its peg. XX */ XX for (; x != destx; x+=dx) { XX if (moveleft) XX delch(); XX else XX insch(' '); XX refresh(); XX } XX XX /* XX * Slip the ring on the top of the peg XX */ XX move(pegtop, 0); XX clrtoeol(); XX y++; XX mvaddstr(y, x, ring[ringno]); XX refresh(); XX XX /* XX * Now slide the ring the rest of the way down the peg. XX */ XX for (y=pegtop+1; y < LINES - toheight - 4; y++) { XX strncpy(blotbuf, blotter+(MAX_RINGS-ringno), ringsize); XX blotbuf[ringsize] = '\0'; XX mvaddstr(y, x, blotbuf); XX mvaddstr(y+1, x, ring[ringno]); XX refresh(); XX } XX XX /* XX * Update the peg stack to show that the ring has been moved. XX */ XX push(to, ringno); XX return; XX} XX XXLight(peg) XXint peg; XX XX{ XX int ringno, h, x, y; XX XX push(peg, ringno = pop(peg)); XX h = peg_height(peg); XX y = LINES - 3 - h; XX x = pegcol[peg] - ringno; XX move(y, x); XX standout(); XX addstr(ring[ringno]); XX standend(); XX refresh(); XX} XX XXDouse(peg) XXint peg; XX XX{ XX int ringno, h, x, y; XX XX push(peg, ringno = pop(peg)); XX h = peg_height(peg); XX y = LINES - 3 - h; XX x = pegcol[peg] - ringno; XX move(y, x); XX standend(); XX addstr(ring[ringno]); XX refresh(); XX} SHAR_EOF if test 2530 -ne "`wc -c move.c`" then echo shar: error transmitting move.c '(should have been 2530 characters)' fi echo shar: extracting pegs.c '(236 characters)' sed 's/^XX//' << \SHAR_EOF > pegs.c XX#include "hanoi.h" XX XXstatic int peg[3][MAX_RINGS]; XXstatic int peg_index[3]; XX XXint pop(p) XXint p; XX XX{ XX return peg[p][--peg_index[p]]; XX} XX XXpush(p, n) XXint p, n; XX XX{ XX peg[p][peg_index[p]++] = n; XX} XX XXpeg_height(p) XXint p; XX XX{ XX return peg_index[p]; XX} SHAR_EOF if test 236 -ne "`wc -c pegs.c`" then echo shar: error transmitting pegs.c '(should have been 236 characters)' fi # End of shell archive exit 0