DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦ebdf26667⟧ TextFile

    Length: 18986 (0x4a2a)
    Types: TextFile
    Names: »mastrm.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Mastrm/mastrm.c« 

TextFile

/*****************************************************************************

  This game, Master Mind, was written by Peter E. Granger and released to
  the public domain via Usenet on Sept. 1, 1987.  Master Mind is based on
  the game by the same name which is  marketed by Invicta Plastics.  This
  game has not been licensed or recognized in anyway by Invicta Plastics.
  Master Mind, as presented here, is intended solely for the enjoyment of
  the public, and is not to be used for profit.  Recipients are permitted
  to redistribute this  code as long as  they do not  attempt to gain any
  profit from it, and may edit this code as they see fit.

                                                      - Pete Granger

 ***************************************************************************/

#include <stdio.h>

#define FALSE 0
#define TRUE 1
#define NONE 0
#define WHITE 1
#define BLACK 2
#define BAD_COLOR -1

	struct peg { int color;
				 int used   };

	struct guess { struct peg pegs[4];
				   int blacks, whites  };
				   
	static char *col[6] = { "white",
                            "black",
                            "red",
                            "green",
                            "yellow",
                            "blue"    };
	int dig[6];
	int cur;
	struct guess guesses[18];
	struct guess dummy[18];
	struct guess code;
	int game_won, player, check, cons;

setcolors()
{
	extern int dig[];
	int x, val, y;
	int digit_found, place_found;

	for (x = 0; x < 6; x++)
		dig[x] = BAD_COLOR;
	for (x = 6; x > 1; x--)
	{
		val = rand() % x;
		place_found = FALSE;
		while (!place_found)
		{
			digit_found = FALSE;
			for (y = 0; y < (6 - x); y++)
				if (val == dig[y])
					digit_found = TRUE;
			if (!digit_found)
			{
				dig[y] = val;
				place_found = TRUE;
			}
			else
				val = (val + 5) % 6;
		}
	}
	dig[5] = 15 - dig[4] - dig[3] - dig[2] - dig[1] - dig[0];
}

set_dummy()
{
	extern struct guess guesses[];
	extern struct guess dummy[];
	extern int cur;

	int x;

		dummy[cur].blacks = dummy[cur].whites = 0;
		for (x = 0; x < 4; x++)
		{
			dummy[cur].pegs[x].used = NONE;
			dummy[cur].pegs[x].color = guesses[cur].pegs[x].color;
		}
}

make_code(ges)

struct guess *ges;
{
	int x, temp;

	for (x = 0; x < 4; x++)
	{
		temp = ges->pegs[x].color = rand() % 6;
		ges->blacks = 0;
		ges->whites = 0;
	}
}

find_digit(col_name)

char col_name[7];
{
	extern int dig[];

	int s;

	for (s = 0; s < 6; s++)
		if (strlen(col_name) == strlen(col[dig[s]]) && 
			!(strncmp(col[dig[s]],col_name,strlen(col_name))))
				return(s);
	return(BAD_COLOR);
}

get_code(kode)

struct guess *kode;

{
	extern int cur;

	char c[4][7];
	int bad_in, code_valid;
	int x;

	code_valid = bad_in = FALSE;
	kode->blacks = kode->whites = 0;
	while (!code_valid)
	{
		code_valid = TRUE;
		if (bad_in)
			printf("Previous code contained invalid color.\n");
		if (player)
			printf("\nPlease enter guess #%d -> ",cur + 1);
		else
			printf("Please enter the correct code -> ");
		scanf("%s %s %s %s",c[0],c[1],c[2],c[3]);
		while (getchar() != '\n');
		if (!player)
			printf("\n");
		for (x = 0; x < 4; x++)
		{
			kode->pegs[x].used = NONE;
			kode->pegs[x].color = find_digit(c[x]); 
			if (kode->pegs[x].color == BAD_COLOR)
			{
				code_valid = FALSE;
				bad_in = TRUE;
			}
		}
	}
}

score()
{
	extern struct guess code;
	extern struct guess guesses[];
	extern int game_won;

	int x, y;

	for (x = 0; x < 4; x++)
		guesses[cur].pegs[x].used = code.pegs[x].used = NONE;
	for (x = 0; x < 4; x++)
		if (guesses[cur].pegs[x].color == code.pegs[x].color)
		{
			code.pegs[x].used = guesses[cur].pegs[x].used = BLACK;
			guesses[cur].blacks++;
			if (player)
				printf("b");
		}
	if (guesses[cur].blacks != 4)
	{
		for (x = 0; x < 4; x++)
			for (y = 0; y < 4; y++)
				if (guesses[cur].pegs[x].color == code.pegs[y].color &&
				    !code.pegs[y].used && !guesses[cur].pegs[x].used)
				{
					code.pegs[y].used = guesses[cur].pegs[x].used = WHITE;
					guesses[cur].whites++;
					if (player)
						printf("w");
				}
	}
	else
		game_won = TRUE;
	if (player)
		if (guesses[cur].blacks != 0 || guesses[cur].whites != 0)
			printf("\n\n");
		else
			printf("No score.\n\n");
}

rest()
{
	printf("\n-- More --   ");
	while (getchar() != '\n');
}

print_instructions()
{
printf ("\n\n                    Instructions for Master Mind\n");
printf ("                                  by\n");
printf ("                             Pete Granger\n\n");
printf ("OBJECT: To match the four color code set by your opponent, using\n");
printf ("        clues from previous guesses.\n\n");
printf ("METHOD: Begin by telling the computer whether you wish to guess,\n");
printf ("        or to create the code which it will guess.  It is usually\n");
printf ("        more interesting to be the guesser, but I wanted you to \n");
printf ("        have the option.\n\n");
printf ("        First, we will cover how to play if you are guessing:\n\n");
printf ("        You will be asked to specify whether you want 'coaching'.\n");
printf ("        This means, the computer will tell you whether your guess\n");
printf ("        is inconsistent with information from previous guesses (it\n");
printf ("        is considered inconsistent if it cannot be the correct\n");
printf ("        code, and you could deduce this).\n\n");
rest();
printf ("        You will then be asked for your first guess.  A guess is\n");
printf ("        a set of four colors, separated by at least one space. \n");
printf ("        The valid colors are:\n\n");
printf ("            black    blue    green    red    white    yellow\n\n");
printf ("        Note that these spellings must be used exactly.  If you\n");
printf ("        make a mistake the machine will let you know, and give\n");
printf ("        another chance.\n\n");
printf ("        The machine will then return your score for that guess.\n");
printf ("        Score is given in black and white pegs (b and w).  A black\n");
printf ("        score peg means that one of your guessed colors is in the\n");
printf ("        correct place.  A white score peg means that one of your\n");
printf ("        guessed colors appears in the correct code, but not in\n");
printf ("        the same location. (If you have selected coaching, that\n");
printf ("        will occur at this time also.)\n\n");
printf ("        You will now be given a choice of 'guess, refresh, hint\n");
printf ("        or quit'.  Enter your choice.  Either first letter or the\n");
printf ("        entire word is okay, case is ignored.  If you just hit\n");
printf ("        return, this is taken as meaning 'guess'.\n");
rest();
printf ("        GUESS: Make another guess, same as before, using the\n");
printf ("               score from previous guesses to make deductions.\n");
printf ("               You have 18 chances to find the right code.\n\n");
printf ("        REFRESH: Shows all your previous guesses and scores.\n\n"); 
printf ("        HINT: By entering the number of  a previous guess, and one\n");
printf ("              of the pegs in that guess, you may find out what \n");
printf ("              score that particular peg received.  Note:  If you\n");
printf ("              have a color in your guess twice, and it is only in\n");
printf ("              the code once, or vice-versa, it will only receive\n");
printf ("              one scoring peg, black taking precedence over white.\n");
printf ("              Hence, it may sometimes be in your best interest to\n");
printf ("              ask for the hint on the first instance of the color\n");
printf ("              in your guess.\n\n");
printf ("        QUIT: You don't want to play anymore.  Remember, the code\n");
printf ("              will not be revealed if you quit.\n\n");
printf ("        When you find the correct sequence, the computer will let\n");
printf ("        you know, and ask if you wish to begin another game.  The\n");
printf ("        default value for this is 'no'.\n");
rest();
printf ("        Now we will consider how to play if you wish to make up\n");
printf ("        the code and have the computer guess:\n\n");
printf ("        You will be asked whether you want the computer to double\n");
printf ("        your scoring of its guesses.  If you desire this, each \n");
printf ("        time you give the computer a score, it score the guess\n");
printf ("        itself.  If the two scores are different, it will inform\n");
printf ("        you of your mistake, and the score it generates will re-\n");
printf ("        place the one you gave.  If you wish your scores checked,\n");
printf ("        you must enter the correct code, so that the computer has\n");
printf ("        data to check the scores you give.  Don't worry, I haven't\n");
printf ("        designed this game to cheat.  The code you enter will be\n");
printf ("        ignored when the computer makes its guess.\n\n");
printf ("        If you do not want double checking, you can refuse it.\n");
printf ("        In this case, any valid score you give will be accepted.\n");
printf ("        The default value for checking is 'yes'.\n");
printf ("        The computer will now make its first guess.  You will be\n");
printf ("        asked for the number of black pegs the guess receives (for\n");
printf ("        each instance of the right color in the right position),\n");
printf ("        up to four.  If you do not give a valid answer (0-4), you\n");
printf ("        will be queried until you do.\n");
rest();
printf ("\n\n");
printf ("        If you give three or four black pegs, it is not possible\n");
printf ("        for any white pegs to be given.  Otherwise, you will be\n");
printf ("        asked for the number of white pegs until you give a valid\n");
printf ("        valid answer, zero to (4 - blacks).\n\n");
printf ("        At this point, if you requested it, your scoring will be\n");
printf ("        checked by the computer.\n\n");
printf ("        The computer will continue to guess in this manner, making\n");
printf ("        certain that each guess is consistent with all previous\n");
printf ("        information, until it receives a score of four black pegs.\n");
printf ("        This will generally take from four to seven guesses, but\n");
printf ("        the machine has been known to get lucky, and break the \n");
printf ("        code on the second guess.  If at any point the computer\n");
printf ("        has exhausted all possible guesses, and found none to be\n");
printf ("        consistent with the information you have given, it will \n");
printf ("        report this error and end the game.\n\n");
printf ("        Good luck, and enjoy Master Mind!\n\n");
rest();
system("clear");
}

consistent()
{
	extern int player, cons;
	extern int cur;
	extern struct guess dummy[];
	extern struct guess guesses[];

	int x, y, z;

	for (z = 0; z < cur; z++)
	{
		dummy[z].blacks = dummy[z].whites = 0;
		for (x = 0; x < 4; x++)
			guesses[cur].pegs[x].used = dummy[z].pegs[x].used = NONE;
		for (x = 0; x < 4; x++)
			if (guesses[cur].pegs[x].color == dummy[z].pegs[x].color)
			{
				dummy[z].pegs[x].used = guesses[cur].pegs[x].used = BLACK;
				dummy[z].blacks++;
			}
		if (dummy[z].blacks != 4)
		{
			for (x = 0; x < 4; x++)
				for (y = 0; y < 4; y++)
					if (guesses[cur].pegs[x].color == dummy[z].pegs[y].color &&
					    !dummy[z].pegs[y].used && !guesses[cur].pegs[x].used)
					{
						dummy[z].pegs[y].used = guesses[cur].pegs[x].used = 
							WHITE;
						dummy[z].whites++;
					}
		}
	}
	cons = TRUE;
	for (z = 0; z < cur; z++)
	{
		if (dummy[z].blacks != guesses[z].blacks ||
			dummy[z].whites != guesses[z].whites)
		{
			if (cons)
			{
				cons = FALSE;
				if (player)
					printf("Inconsistent guess.  If this were correct:\n");
			}
			if (player)
			{
			printf("    guess #%d would have gotten ",z + 1);
			printf("%d black and %d white.\n",dummy[z].blacks,dummy[z].whites);
			}
		}
	}
	if (cons && player)
		printf("This guess is consistent with all previous clues.\n");
}

refresh()
{
	extern struct guess guesses[];
	int x, y;

	system("clear");
	if (!player && check)
	{
		printf("Your correct sequence:  ");
		for (y = 0; y < 4; y++)
			printf("%-8s",col[dig[code.pegs[y].color]]);
		printf("\n\n");
	}
	for (x = 0; x < cur; x++)
	{
		printf("%2d.  ",x + 1);
		for (y = 0; y < 4; y++)
			printf("%-8s",col[dig[guesses[x].pegs[y].color]]);
		for (y = 0; y < guesses[x].blacks; y++)
			printf("b");
		for (y = 0; y < guesses[x].whites; y++)
			printf("w");
		printf("\n");
	}
	printf("\n");
}

player_plays()
{
	extern int game_won;
	extern struct guess code;
	extern struct guess guesses[];
	extern int dig[];
	extern int cur;

	char inst, action;
	int coach, quit;
	int t, w, x, y, z;

	coach = quit = FALSE;
	printf("Do you want coaching, y/n [default is n] -> ");
	if ((inst = getchar()) != '\n')
		while (getchar() != '\n');
	if (inst == 'y' || inst == 'Y')
		coach = TRUE;
	printf("\nChoosing a code for you to guess.\n");
	t = rand() % 3 + 2;
	sleep(t);
	make_code(&code);
	for (cur = 0; cur < 18 && !game_won;)
	{
		if (cur)
		{
			printf("guess, refresh, hint, or quit [default is guess] -> ");
			if ((action = getchar()) != '\n')
				while (getchar() != '\n');
		}
		else
			action = 'g';
		switch (action)
		{
			case 'q':
			case 'Q':
				cur = 18;
				quit = TRUE;
				break;
			case 'r':
			case 'R':
				refresh();
				break;
			case 'h':
			case 'H':
				printf("\n");
				z = 0;
				while (z < 1 || z > cur)
				{
					z = 0;
					printf("Enter the guess you need the hint for -> ");
					while((t = getchar()) != '\n')
						z = z * 10 + t - '0';
				}
				w = 0;
				while (w < 1 || w > 4)
				{
					w = 0;
					printf("Which peg of guess #%d -> ",z);
					while((t = getchar()) != '\n')
						w = w * 10 + t - '0';
				}
				printf("In guess #%d, peg #%d received ",z,w);
				if (guesses[z - 1].pegs[w - 1].used == BLACK)
					printf("a black peg.\n");
				if (guesses[z - 1].pegs[w - 1].used == WHITE)
					printf("a white peg.\n");
				if (guesses[z - 1].pegs[w - 1].used == NONE)
					printf("no peg.\n");
				printf("\n");
				break;
			default:
 				get_code(&guesses[cur]);
				set_dummy();
				if (coach && cur)
					consistent();
				score();
				cur++;
				break;
		}
	}
	if (game_won)
	{
		printf("    Congratulations, human!  You broke the code in %d",cur);
		if (cur != 1)
			printf(" guesses.\n");
		else
			printf(" guess.  What luck!\n");
	}
	else if (!quit)
	{
		printf("    Sorry.  You've run out of guesses.\n");
		printf("    The correct code was:   %-8s %-8s %-8s %-8s\n",
				col[dig[code.pegs[0].color]],
				col[dig[code.pegs[1].color]],
				col[dig[code.pegs[2].color]],
				col[dig[code.pegs[3].color]]);
	}
	else
		printf("Was that too tough for you?  I'll be nicer next time.\n");
}

tell_guess()
{
	extern int cur;
	extern struct guess guesses[];
	extern int dig[];

	if (!check)
		printf("\n");
	if (cur < 10)
		printf(" ");
	printf("    Guess #%d:   %-8s %-8s %-8s %-8s\n\n",cur + 1,
			col[dig[guesses[cur].pegs[0].color]],
			col[dig[guesses[cur].pegs[1].color]],
			col[dig[guesses[cur].pegs[2].color]],
			col[dig[guesses[cur].pegs[3].color]]);
}

get_score()
{
	extern struct guess guesses[];
	extern int cur;
	extern int check;

	int t, w, x;

	w = -1;
	while (w < 0 || w > 4)
	{
		w = 0;
		printf("How many black pegs do I get -> ");
		while((t = getchar()) != '\n')
			w = w * 10 + t - '0';
	}
	if (w == 4 || w == 3)
		x = 0;
	else
		x = -1;
	while (x < 0 || x > 4 - w)
	{
		x = 0;
		printf("How many white pegs do I get -> ");
		while((t = getchar()) != '\n')
			x = x * 10 + t - '0';
	}
	if (check)
	{
		score();
		if (guesses[cur].blacks != w || guesses[cur].whites != x)
		{
			printf("You seem to have made a mistake.  ");
			printf("My correct score is %d black",guesses[cur].blacks);
			if (guesses[cur].blacks != 1)
				printf("s");
			printf(" and %d white",guesses[cur].whites);
			if (guesses[cur].whites != 1)
				printf("s");
			printf(".\n\n");
		}
		else
			printf("\n");
	}
	else
	{
		guesses[cur].blacks = w;
		guesses[cur].whites = x;
		if (guesses[cur].blacks == 4)
			game_won = TRUE;
	}
}

machine_plays()
{
	extern struct guess code;
	extern struct guess guesses[];
	extern int cur;
	extern int check, game_won;

	int w, x, y, z;
	int randomizing = TRUE;
	int quit = FALSE;
	int refreshed;
	char ans;

	check = TRUE;
	printf("Do you want me to double check you, y/n [default is y] -> ");
	if ((ans = getchar()) != '\n')
		while (getchar() != '\n');
	if (ans == 'n' || ans == 'N')
		check = FALSE;
	if (check)
		get_code(&code);
	cur = 0;
	make_code(&guesses[cur]);
	set_dummy();
	tell_guess();
	get_score();
	for (++cur; cur < 6 && !game_won && randomizing && !quit;)
	{
		refreshed = FALSE;
		if (!(cur % 2) && cur > 3)
		{
			refresh();
			refreshed = TRUE;
		}
		x = 0;
		cons = FALSE;
		while (!cons && x < 1200)
		{
			x++;
			make_code(&guesses[cur]);
			consistent();
		}
		if (cons)
		{
			set_dummy();
			tell_guess();
			get_score();
			cur++;
		}
		else
			randomizing = FALSE;
	}
	if (!game_won)
		for (cur; cur < 18 && !game_won && !quit; cur++)
		{
			if (!(cur % 2) && cur > 3 && !refreshed)
				refresh();
			cons = FALSE;
			for (w = 0; w < 6 && !cons; w++)
			for (x = 0; x < 6 && !cons; x++)
			for (y = 0; y < 6 && !cons; y++)
			for (z = 0; z < 6 && !cons; z++)
			{
				guesses[cur].pegs[0].color = w;
				guesses[cur].pegs[1].color = x;
				guesses[cur].pegs[2].color = y;
				guesses[cur].pegs[3].color = z;
				guesses[cur].blacks = guesses[cur].whites = 0;
				consistent();
			}
			if (cons)
			{
				set_dummy();
				tell_guess();
				get_score();
			}
			else
			{
				printf("No guess is consistent.  You must have cheated!\n");
				printf("Can't recover from this.  Goodbye!\n");
				quit = TRUE;
			}
		}
	if (game_won)
	{
		printf("I broke your code in %d ",cur);
		if (cur != 1)
			printf("guesses.\n");
		else
			printf("guess.  Machines can get lucky, too!\n");
	}
	else if (!quit)
		printf("I didn't break your code.  You win this time!\n");
}

main()
{
	extern int cur, game_won, player;
	extern int dig[];
	extern struct guess code;
	extern struct guess guesses[];

	char more, inst;
	int play_game = TRUE;
	int z;

	system("clear");
	z=time();
	srand(z);
	printf("Would you like instructions, y/n [default is n] -> ");
	if ((inst = getchar()) != '\n')
		while (getchar() != '\n');
	if (inst == 'y' || inst == 'Y')
		print_instructions();
	while (play_game)
	{
		player = TRUE;
		game_won = FALSE;
		printf("Do you want to guess, or make the code,");
		printf(" g/m [default is g] -> ");
		if ((inst = getchar()) != '\n')
			while (getchar() != '\n');
		if (inst == 'm' || inst == 'M')
			player = FALSE;
		setcolors();
		if (player)
			player_plays();
		else
			machine_plays();
		printf("\nWould you like to play again, y/n [default is n] -> ");
		if ((more = getchar()) != '\n')
			while (getchar() != '\n');
		if (more != 'y' && more != 'Y')
			play_game = FALSE;
		system("clear");
	}
}