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

⟦bf43c8444⟧ TextFile

    Length: 14231 (0x3797)
    Types: TextFile
    Names: »main.c«

Derivation

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

TextFile

#define EXTERN

#include "challenge.h"

int quit();

/*
   main program performs program parameter checking, curses initialization
   and game set up
*/
main(argc,argv)
    int argc;
    char *argv[];
{
    char c;

    /*
       parameter checking.  valid parameters are -s and -d
    */
    while(argc > 1) {
	if(argv[1][0] == '-') {
	    switch(argv[1][1]) {
	    case 'd':
		depth = atoi(&argv[1][2]);
		if(depth < 0) {
		    printf("depth should be 0 or larger\n");
		    exit(0);
		}
		break;
	    case 's':
		size = atoi(&argv[1][2]);
		if(size < 1 || size > 8) {
		    printf("size should be between 1 and 8\n");
		    exit(0);
		}
		break;
	    case 'a':
		no_scoring = TRUE;
		analysing = TRUE;
		if(argv[1][2] != 0) {
		    logfile = fopen(&argv[1][2], "r");
		    if(logfile == NULL) {
			printf("cannot open game file\n");
			exit(0);
		    }
		}
		break;
	    case 'o':
		check_options(&argv[1][2]);
		break;
	    default:
		usage();
	    }
	}
	else usage();
	argv++;
	argc--;
    }
    /* general initializations */
    seed = time(0);
#ifdef TIMER
    signal(SIGALRM,timer);
#endif
    signal(SIGQUIT,quit);
    signal(SIGINT,quit);
    initscr();
    crmode();
    noecho();
    clear();
    if(!analysing) {
        move(COMMAND_LINE - 2, 1);
	printw("do you want instructions? (y/n) ");
	refresh();
	if(yesno()) {
	    put_instructions(TRUE);
	    clear();
	}
	move(COMMAND_LINE - 1, 1);
	printw("do you want a demonstration game? (y/n) ");
	refresh();
	if(yesno()) {
	    for(;;) {
		demo = COMPUTER;
		init();
		redraw();
		do_demo();
		move(COMMAND_LINE + 1,1);
		clrtoeol();
		move(COMMAND_LINE,1);
		clrtoeol();
		printw("another demo? (y/n) ");
		refresh();
		if(!yesno()) {
		    break;
		}
	    }
	    human_score = 0;
	    computer_score = 0;
	    demo = 0;
	}
	move(COMMAND_LINE,1);
	clrtoeol();
	printw("do you want me to start? (y/n) ");
	refresh();
	if(yesno()) {
	    start_player = COMPUTER;
	}
	signal(SIGINT, nasty);
	signal(SIGQUIT, nasty);
    }
    /* loop through games */
    for(;;) {
	if(!analysing || no_scoring) {
	    init();
	    redraw();
	} else if(!no_scoring) {
	    move(COMMENT_LINE, 1);
	    clrtoeol();
	    move(COMMAND_LINE - 1, 1);
	    clrtoeol();
	    move(COMMAND_LINE, 1);
	    clrtoeol();
	    printw("command:");
	    move(COMMAND_LINE + 1, 1);
	    clrtoeol();
	    printw("you have now the additional b command available for back-up");
	    display_extra();
	    refresh();
	}
	play_challenge(start_player);
	move(COMMAND_LINE + 1,1);
	clrtoeol();
	move(COMMAND_LINE,1);
	clrtoeol();
	signal(SIGINT, quit);
	signal(SIGQUIT, quit);
	printw("another game? (y/n) ");
	if(!analysing) {
	    printw("or analyse game? (a) ");
	}
	refresh();
	while(TRUE) {
	    c = getch();
	    if(c == 'N') c = 'n';
	    if(c == 'Y') c = 'y';
	    if((c == 'n') || (c == 'y') || ((c == 'a') && !analysing)) {
		break;
	    }
	    (void) putchar(007);
	    fflush(stdout);
	}
	refresh();
	if(c == 'n') {
	    break;
	}
	if(analysing && !no_scoring) {
	    analysing = FALSE;
	    logfile = save_logfile;
	} else if(c == 'a') {
	    analysing = TRUE;
	    save_logfile = logfile;
	    logfile = NULL;
	}
	if(!analysing) {
	    signal(SIGINT, nasty);
	    signal(SIGQUIT, nasty);
	    interchange(&start_player);
	}
    }
    quit();
}

/*
   play the game; alternate between computer strategy and human.
   stop when the game is finished or the result is one of
   RESIGN, DRAWN, WIN.  the computer strategy should not return
   WIN, and DRAWN only if the human is consulted!
   PASS is only permitted to restart a game with the proper player
   starting.
*/
play_challenge(player)
    int player;
{
    int finished;
    int card, card1;

again:
    finished = FALSE;
    if(analysing) {
	player = HUMAN;
    }
    while(!finished) {
	move(COMMAND_LINE, COMMAND_POS);
	if(player == COMPUTER) {
	    clrtoeol();
	    printw("thinking....");
	    move(COMMENT_LINE, 1);
	    clrtoeol();
	    refresh();
	    card = strategy(COMPUTER);
	    card1 = card;
	    if(card < MAX_CARD) {
		card1 = computer[card];
	    }
	} else {
	    clrtoeol();
	    refresh();
	    card = human_interface();
	    if(card == ANAL_END) {
		return;
	    }
	    card1 = card;
	    if(card < MAX_CARD) {
		card1 = human[card];
	    }
	}
	if(card1 == PICK_UP) {
		save_pick_up();
	}
	if(card != BACK_UP) {
		moves[nr_moves++] = card1;
	}
	if(logfile != NULL && !analysing) {
	    record(player, card1);
	}
	if(card != PASS) {
	    move(COMMAND_LINE - 1, 1);
	    clrtoeol();
	    if(card <= PICK_UP) {
		finished = do_move(player, card);
	    } else if(card != BACK_UP) {
		finished = TRUE;
		break;
	    }
	    move(COMMAND_LINE - 1, 1);
	    clrtoeol();
	    if(card != BACK_UP) {
		if(player == COMPUTER) {
		    if(card != PICK_UP) {
			printw("computer plays ");
			display_full(top);
		    } else {
			printw("computer picks up");
		    }
		}
	    } else {
		back_up(COMPUTER);
		back_up(HUMAN);
		move(COMMAND_LINE - 1, 1);
		printw("backed_up one move");
	    }
	}
	if(!finished && card != BACK_UP) {
	    interchange(&player);
	}
    }
    if(player == COMPUTER) {
	if(card <= PICK_UP) {
	    printw(", and wins");
	    if(!analysing) {
		computer_score += 2;
	    }
	} else if(card == RESIGN) {
	    printw("computer resigns");
	    if(!analysing) {
		human_score += 2;
	    }
	} else {
	    printw("game is a draw");
	    if(!analysing) {
		computer_score++;
		human_score++;
	    }
	}
	/* NOTE: no case for WIN! */
    } else {
	if(card <= PICK_UP || card == WIN) {
	    printw("you win");
	    if(card != WIN) {
		moves[nr_moves++] = PASS;
	    } else {
		nr_moves--;
	    }
	    if(!analysing) {
		human_score += 2;
	    }
	} else if(card == RESIGN) {
	    printw("you resign");
	    nr_moves--;
	    if(!analysing) {
		computer_score += 2;
	    }
	} else {
	    printw("the game is a draw");
	    nr_moves--;
	    if(!analysing) {
		computer_score++;
		human_score++;
	    }
	}
    }
    if(analysing) {
	goto again;
    }
    if(logfile != NULL && !analysing) {
	record_end();
    }
}

save_pick_up()
{
    int i;
    unsigned long pu = 0l;

    for(i = 0; i < nr_table; i++) {
	pu += (1 << table[i]);
    }
    pick_ups[nr_moves] = pu;
}

back_up(player)
{
    int i, j, m, *nr_deck;
    char *deck;
    unsigned long pu;

    if(player == COMPUTER) {
	deck = &computer[0];
	nr_deck = &nr_computer;
    } else {
	deck = &human[0];
	nr_deck = &nr_human;
    }
    m = moves[--nr_moves];
    if(m == PASS) {
	return;
    }
    if(m != PICK_UP) {
	deck[(*nr_deck)++] = m;
	print_card(player, m);
	for(i = 0; i < nr_table; i++) {
	    if(table[i] == m) {
		table[i] = table[--nr_table];
		clear_card(TABLE, m);
		break;
	    }
	}
    } else {
	pu = pick_ups[nr_moves];
	i = 0;
	while(i < max_card && pu != 0L) {
	    if(pu & 1) {
		table[nr_table++] = i;
		print_card(TABLE, i);
	    }
	    i++;
	    pu >>= 1;
	}
	for(i = 0; i < nr_table; i++) {
	    m = table[i];
	    for(j = 0; j < *nr_deck; j++) {
		if(deck[j] == m) {
		    deck[j] = deck[--(*nr_deck)];
		    clear_card(player, m);
		}
	    }
	}
    }
    if(nr_moves > 0) {
	top = moves[nr_moves - 1];
	if(top == PICK_UP) {
	    top = -1;
	}
    } else {
	top = -1;
    }
    print_top(top);
}

/* check the validity of the card played; card is an index to the hand */
valid(player, card)
    int player, card;
{
    int value, suit, tvalue, tsuit, *nr_deck;
    char *deck;

    if(player == COMPUTER) {
	deck = &computer[0];
	nr_deck = &nr_computer;
    } else {
	deck = &human[0];
	nr_deck = &nr_human;
    }
    if(card == PICK_UP) {
	return(nr_table > 0);
    }
    if(card >= *nr_deck) {
	return(FALSE);
    }
    if(nr_table == 0) {
	return(TRUE);
    }
    value = VALUE(deck[card]);
    suit = SUIT(deck[card]);
    tvalue = VALUE(top);
    tsuit = SUIT(top);
    if(suit == tsuit && value < tvalue) {
	return(TRUE);
    }
    if((player == COMPUTER && suit != SPADES) ||
       (player == HUMAN && suit != HEARTS)) {
	return(FALSE);
    }
    return(suit != tsuit);
}

/* executes players move; card is an index to the hand */
do_move(player, card)
    int player;
    char card;
{
    int i, *nr_deck;
    char *deck;

    if(player == COMPUTER) {
	deck = &computer[0];
	nr_deck = &nr_computer;
    } else {
	deck = &human[0];
	nr_deck = &nr_human;
    }
    if(card != PICK_UP) {
	top = deck[card];
	table[nr_table++] = top;
	print_card(TABLE, top);
	print_top(top);
	deck[card] = deck[--(*nr_deck)];
	clear_card(player, top);
	return(*nr_deck == 0);
    } else {
	for(i = 0; i < nr_table; i++) {
	    deck[(*nr_deck)++] = table[i];
	    print_card(player, table[i]);
	    clear_card(TABLE, table[i]);
	}
	nr_table = 0;
	top = -1;
	print_top(top);
	return(FALSE);
    }
}

/* set up a new game */
init()
{
    char cards[MAX_CARD];
    int i;
    char *c, *h;
    int s = size * 4;
    int j, value, suit, card;

    size2 = size * 2;
    max_card = size * 4;
    if(no_scoring) {
	if(logfile != NULL) {
	    read_game();
	    return;
	}
	for(i = 0; i < max_card; i++) {
	    human[i] = i;
	}
	nr_human = max_card;
	nr_computer = 0;
	nr_table = 0;
	top = -1;
	nr_moves = 0;
	move_logged = 0;
	return;
    }
    for(i = 0; i < max_card; i++) {
	cards[i] = i;
	table[i] = -1;
    }
    top = -1;
    c = &computer[0];
    h = &human[0];
    for(i = max_card - 1; i >= size2; i--) {
	j = rnd(s--);
	card = cards[j];
	cards[j] = cards[i];
	value = VALUE(card);
	suit = SUIT(card);
	if(suit <= CLUBS) {
	    *c++ = card;
	    *h++ = (3 - suit) + value * 4;
	}
    }
    for(i = 0; i < size2; i++) {
	card = cards[i];
	value = VALUE(card);
	suit = SUIT(card);
	if(suit <= CLUBS) {
	    *h++ = card;
	    *c++ = (3 - suit) + value * 4;
	}
    }
    for(i = size2; i < max_card; i++) {
	*h++ = -1;
	*c++ = -1;
    }
    nr_computer = size2;
    nr_human = size2;
    nr_table = 0;
    for(i = 0; i < max_card; i++) {
	s_computer[i] = computer[i];
	s_human[i] = human[i];
    }
    nr_moves = 0;
    move_logged = 0;
}

draw_score()
{
    if(no_scoring) {
	move(0, MARGIN + size2);
	if(start_player == HUMAN) {
	    printw("   human vs. computer         ");
	} else {
	    printw("   computer vs. human         ");
	}
    } else {
	move(0, MARGIN + size2);
	if(demo != 0) {
	    printw("computer %2d vs. robot %2d", computer_score, human_score);
	} else if(start_player == HUMAN) {
	    printw("human %2d vs. computer %2d", human_score, computer_score);
	} else {
	    printw("computer %2d vs. human %2d", computer_score, human_score);
	}
    }
}

/* draw or redraw the play */
redraw()
{
    int i;

    clear();
    draw_score();
    move(COMPUTER, MARGIN);
    printw("computer: SPADES:");
    move(COMPUTER + 1, MARGIN);
    printw("           clubs:");
    move(COMPUTER + 2, MARGIN);
    printw("        diamonds:");
    move(COMPUTER + 3, MARGIN);
    printw("          hearts:");
    move(TABLE, MARGIN);
    printw("   table: spades:");
    move(TABLE + 1, MARGIN);
    printw("           clubs:");
    move(TABLE + 2, MARGIN);
    printw("        diamonds:");
    move(TABLE + 3, MARGIN);
    printw("          hearts:");
    move(HUMAN, MARGIN);
    printw("     you: spades:");
    move(HUMAN + 1, MARGIN);
    printw("           clubs:");
    move(HUMAN + 2, MARGIN);
    printw("        diamonds:");
    move(HUMAN + 3, MARGIN);
    printw("          HEARTS:");
    move(TABLE + 1, 1);
    printw("top:");
    move(COMMAND_LINE, 1);
    printw("command:");
    move(COMMAND_LINE + 1, 1);
    printw("enter: card to play, or p for pick-up, or ? for help, or ! for extra commands");
    for(i = 0; i < nr_computer; i++) {
	print_card(COMPUTER, computer[i]);
    }
    for(i = 0; i < nr_table; i++) {
	print_card(TABLE, table[i]);
    }
    for(i = 0; i < nr_human; i++) {
	print_card(HUMAN, human[i]);
    }
    print_top(top);
    display_extra();
}

/* print a card */
print_card(player, card)
    int player;
    char card;
{
    int value, suit;

    value = VALUE(card);
    suit = SUIT(card);
    move(ROW(player,suit,value),COL(player,suit,value));
    if(card < 0) {
	printw("  ");
	return;
    }
    display_value(value);
}

/* clear the position of a card */
clear_card(player, card)
    int player;
    char card;
{
    int value, suit;

    value = VALUE(card);
    suit = SUIT(card);
    move(ROW(player,suit,value),COL(player,suit,value));
    printw("  ");
}

/* print the top card */
print_top(card)
    char card;
{
    move(TABLE + 2, 1);
    display(card);
}

/* display card: suit and value */
display(card)
    char card;
{
    int value, suit;

    value = VALUE(card);
    suit = SUIT(card);
    if(card < 0) {
	printw("---");
	return;
    }
    display_value(value);
    printw("%c", "scdh"[suit]);
}

/* display value of card */
display_value(value)
    int value;
{
    if(value == C_10) {
	printw("1");
    } else {
	printw(" ");
    }
    printw("%c", "AKQJ098765432"[value]);
}

/* display the name of the card in full */
char *values[] = {
"ace", "king", "queen", "jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"};

char *suits[] = {
"spades", "clubs", "diamonds", "hearts"};

display_full(card)
    char card;
{
    int value, suit;

    value = VALUE(card);
    suit = SUIT(card);
    printw(values[value]);
    printw(" of ");
    printw(suits[suit]);
}

/* interchange players */
interchange(p)
    int *p;
{
    *p = COMPUTER + HUMAN - *p;
}

/* require y or n answer */
yesno()
{
    char c = 0;

    while((c != 'n') && (c != 'y')) {
	c = getch();
	if(c == 'N') c = 'n';
	if(c == 'Y') c = 'y';
	if((c != 'n') && (c != 'y')) {
	    (void) putchar(007);
	    fflush(stdout);
	}
    }
    return(c == 'y');
}

quit()
{
#ifdef TIMER
    alarm(0);
#endif
    move(COMMAND_LINE + 1, 0);
    clrtoeol();
    refresh();
    endwin();
    if(!no_scoring) {
	printf("your final score was %d, the computer had %d\n",
	    human_score, computer_score);
    }
    exit(0);
}

nasty()
{
#ifdef TIMER
    alarm(0);
#endif
    move(COMMENT_LINE, 1);
    clrtoeol();
    move(COMMAND_LINE, 1);
    clrtoeol();
    printw("just when i had such a good game going!");
    computer_score += 2;
    quit();
}

rnd(mod)
    int mod;
{
    if(mod <= 0) {
	return(0);
    }
    return((((seed = seed*11109+13849) >> 16) & 0xffff) % mod);
}

usage()
{
    printf("usage: challenge [-s#] [-d#]\n");
    exit(0);
}