xref: /csrg-svn/games/mille/comp.c (revision 33170)
130198Sbostic /*
230198Sbostic  * Copyright (c) 1982 Regents of the University of California.
3*33170Sbostic  * All rights reserved.
4*33170Sbostic  *
5*33170Sbostic  * Redistribution and use in source and binary forms are permitted
6*33170Sbostic  * provided that this notice is preserved and that due credit is given
7*33170Sbostic  * to the University of California at Berkeley. The name of the University
8*33170Sbostic  * may not be used to endorse or promote products derived from this
9*33170Sbostic  * software without specific prior written permission. This software
10*33170Sbostic  * is provided ``as is'' without express or implied warranty.
1130198Sbostic  */
1230198Sbostic 
1330198Sbostic #ifndef lint
14*33170Sbostic static char sccsid[] = "@(#)comp.c	5.2 (Berkeley) 12/29/87";
15*33170Sbostic #endif /* not lint */
1630198Sbostic 
1730198Sbostic # include	"mille.h"
1830198Sbostic 
1930198Sbostic /*
2030198Sbostic  * @(#)comp.c	1.1 (Berkeley) 4/1/82
2130198Sbostic  */
2230198Sbostic 
2330198Sbostic # define	V_VALUABLE	40
2430198Sbostic 
2530198Sbostic calcmove()
2630198Sbostic {
2730198Sbostic 	register CARD		card;
2830198Sbostic 	register int		*value;
2930198Sbostic 	register PLAY		*pp, *op;
3030198Sbostic 	register bool		foundend, cango, canstop, foundlow;
3130198Sbostic 	register unsgn int	i, count200, badcount, nummin, nummax, diff;
3230198Sbostic 	register int		curmin, curmax;
3330198Sbostic 	register CARD		safe, oppos;
3430198Sbostic 	int			valbuf[HAND_SZ], count[NUM_CARDS];
3530198Sbostic 	bool			playit[HAND_SZ];
3630198Sbostic 
3730198Sbostic 	wmove(Score, ERR_Y, ERR_X);	/* get rid of error messages	*/
3830198Sbostic 	wclrtoeol(Score);
3930198Sbostic 	pp = &Player[COMP];
4030198Sbostic 	op = &Player[PLAYER];
4130198Sbostic 	safe = 0;
4230198Sbostic 	cango = 0;
4330198Sbostic 	canstop = FALSE;
4430198Sbostic 	foundend = FALSE;
4530198Sbostic 	for (i = 0; i < NUM_CARDS; i++)
4630198Sbostic 		count[i] = 0;
4730198Sbostic 	for (i = 0; i < HAND_SZ; i++) {
4830198Sbostic 		card = pp->hand[i];
4930198Sbostic 		switch (card) {
5030198Sbostic 		  case C_STOP:	case C_CRASH:
5130198Sbostic 		  case C_FLAT:	case C_EMPTY:
5230198Sbostic 			if (playit[i] = canplay(pp, op, card))
5330198Sbostic 				canstop = TRUE;
5430198Sbostic 			goto norm;
5530198Sbostic 		  case C_LIMIT:
5630198Sbostic 			if ((playit[i] = canplay(pp, op, card))
5730198Sbostic 			    && Numseen[C_25] == Numcards[C_25]
5830198Sbostic 			    && Numseen[C_50] == Numcards[C_50])
5930198Sbostic 				canstop = TRUE;
6030198Sbostic 			goto norm;
6130198Sbostic 		  case C_25:	case C_50:	case C_75:
6230198Sbostic 		  case C_100:	case C_200:
6330198Sbostic 			if ((playit[i] = canplay(pp, op, card))
6430198Sbostic 			    && pp->mileage + Value[card] == End)
6530198Sbostic 				foundend = TRUE;
6630198Sbostic 			goto norm;
6730198Sbostic 		  default:
6830198Sbostic 			playit[i] = canplay(pp, op, card);
6930198Sbostic norm:
7030198Sbostic 			if (playit[i])
7130198Sbostic 				++cango;
7230198Sbostic 			break;
7330198Sbostic 		  case C_GAS_SAFE:	case C_DRIVE_SAFE:
7430198Sbostic 		  case C_SPARE_SAFE:	case C_RIGHT_WAY:
7530198Sbostic 			if (pp->battle == opposite(card) ||
7630198Sbostic 			    (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) {
7730198Sbostic 				Movetype = M_PLAY;
7830198Sbostic 				Card_no = i;
7930198Sbostic 				return;
8030198Sbostic 			}
8130198Sbostic 			++safe;
8230198Sbostic 			playit[i] = TRUE;
8330198Sbostic 			break;
8430198Sbostic 		}
8530198Sbostic 		++count[card];
8630198Sbostic 	}
8730198Sbostic 	if (pp->hand[0] == C_INIT && Topcard > Deck) {
8830198Sbostic 		Movetype = M_DRAW;
8930198Sbostic 		return;
9030198Sbostic 	}
91*33170Sbostic #ifdef DEBUG
9230198Sbostic 	if (Debug)
9330198Sbostic 		fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
9430198Sbostic 			cango, canstop, safe);
95*33170Sbostic #endif
9630198Sbostic 	if (foundend)
9730198Sbostic 		foundend = !check_ext(TRUE);
9830198Sbostic 	for (i = 0; safe && i < HAND_SZ; i++) {
9930198Sbostic 		if (issafety(pp->hand[i])) {
10030198Sbostic 			if (onecard(op) || (foundend && cango && !canstop)) {
101*33170Sbostic #ifdef DEBUG
10230198Sbostic 				if (Debug)
10330198Sbostic 					fprintf(outf,
10430198Sbostic 						"CALCMOVE: onecard(op) = %d, foundend = %d\n",
10530198Sbostic 						onecard(op), foundend);
106*33170Sbostic #endif
10730198Sbostic playsafe:
10830198Sbostic 				Movetype = M_PLAY;
10930198Sbostic 				Card_no = i;
11030198Sbostic 				return;
11130198Sbostic 			}
11230198Sbostic 			oppos = opposite(pp->hand[i]);
11330198Sbostic 			if (Numseen[oppos] == Numcards[oppos] &&
11430198Sbostic 			    !(pp->hand[i] == C_RIGHT_WAY &&
11530198Sbostic 			      Numseen[C_LIMIT] != Numcards[C_LIMIT]))
11630198Sbostic 				goto playsafe;
11730198Sbostic 			else if (!cango
11830198Sbostic 			    && (op->can_go || !pp->can_go || Topcard < Deck)) {
11930198Sbostic 				card = (Topcard - Deck) - roll(1, 10);
12030198Sbostic 				if ((!pp->mileage) != (!op->mileage))
12130198Sbostic 					card -= 7;
122*33170Sbostic #ifdef DEBUG
12330198Sbostic 				if (Debug)
12430198Sbostic 					fprintf(outf,
12530198Sbostic 						"CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
12630198Sbostic 						card, DECK_SZ / 4);
127*33170Sbostic #endif
12830198Sbostic 				if (card < DECK_SZ / 4)
12930198Sbostic 					goto playsafe;
13030198Sbostic 			}
13130198Sbostic 			safe--;
13230198Sbostic 			playit[i] = cango;
13330198Sbostic 		}
13430198Sbostic 	}
13530198Sbostic 	if (!pp->can_go && !isrepair(pp->battle))
13630198Sbostic 		Numneed[opposite(pp->battle)]++;
13730198Sbostic redoit:
13830198Sbostic 	foundlow = (cango || count[C_END_LIMIT] != 0
13930198Sbostic 			  || Numseen[C_LIMIT] == Numcards[C_LIMIT]
14030198Sbostic 			  || pp->safety[S_RIGHT_WAY] != S_UNKNOWN);
14130198Sbostic 	foundend = FALSE;
14230198Sbostic 	count200 = pp->nummiles[C_200];
14330198Sbostic 	badcount = 0;
14430198Sbostic 	curmax = -1;
14530198Sbostic 	curmin = 101;
14630198Sbostic 	nummin = -1;
14730198Sbostic 	nummax = -1;
14830198Sbostic 	value = valbuf;
14930198Sbostic 	for (i = 0; i < HAND_SZ; i++) {
15030198Sbostic 		card = pp->hand[i];
15130198Sbostic 		if (issafety(card) || playit[i] == (cango != 0)) {
152*33170Sbostic #ifdef DEBUG
15330198Sbostic 			if (Debug)
15430198Sbostic 				fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
15530198Sbostic 					C_name[card]);
156*33170Sbostic #endif
15730198Sbostic 			switch (card) {
15830198Sbostic 			  case C_25:	case C_50:
15930198Sbostic 				diff = End - pp->mileage;
16030198Sbostic 				/* avoid getting too close */
16130198Sbostic 				if (Topcard > Deck && cango && diff <= 100
16230198Sbostic 				    && diff / Value[card] > count[card]
16330198Sbostic 				    && (card == C_25 || diff % 50 == 0)) {
16430198Sbostic 					if (card == C_50 && diff - 50 == 25
16530198Sbostic 					    && count[C_25] > 0)
16630198Sbostic 						goto okay;
16730198Sbostic 					*value = 0;
16830198Sbostic 					if (--cango <= 0)
16930198Sbostic 						goto redoit;
17030198Sbostic 					break;
17130198Sbostic 				}
17230198Sbostic okay:
17330198Sbostic 				*value = (Value[card] >> 3);
17430198Sbostic 				if (pp->speed == C_LIMIT)
17530198Sbostic 					++*value;
17630198Sbostic 				else
17730198Sbostic 					--*value;
17830198Sbostic 				if (!foundlow
17930198Sbostic 				   && (card == C_50 || count[C_50] == 0)) {
18030198Sbostic 					*value = (pp->mileage ? 10 : 20);
18130198Sbostic 					foundlow = TRUE;
18230198Sbostic 				}
18330198Sbostic 				goto miles;
18430198Sbostic 			  case C_200:
18530198Sbostic 				if (++count200 > 2) {
18630198Sbostic 					*value = 0;
18730198Sbostic 					break;
18830198Sbostic 				}
18930198Sbostic 			  case C_75:	case C_100:
19030198Sbostic 				*value = (Value[card] >> 3);
19130198Sbostic 				if (pp->speed == C_LIMIT)
19230198Sbostic 					--*value;
19330198Sbostic 				else
19430198Sbostic 					++*value;
19530198Sbostic miles:
19630198Sbostic 				if (pp->mileage + Value[card] > End)
19730198Sbostic 					*value = (End == 700 ? card : 0);
19830198Sbostic 				else if (pp->mileage + Value[card] == End) {
19930198Sbostic 					*value = (foundend ? card : V_VALUABLE);
20030198Sbostic 					foundend = TRUE;
20130198Sbostic 				}
20230198Sbostic 				break;
20330198Sbostic 			  case C_END_LIMIT:
20430198Sbostic 				if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
20530198Sbostic 					*value = (pp->safety[S_RIGHT_WAY] ==
20630198Sbostic 						  S_PLAYED ? -1 : 1);
20730198Sbostic 				else if (pp->speed == C_LIMIT &&
20830198Sbostic 					 End - pp->mileage <= 50)
20930198Sbostic 					*value = 1;
21030198Sbostic 				else if (pp->speed == C_LIMIT
21130198Sbostic 				    || Numseen[C_LIMIT] != Numcards[C_LIMIT]) {
21230198Sbostic 					safe = S_RIGHT_WAY;
21330198Sbostic 					oppos = C_LIMIT;
21430198Sbostic 					goto repair;
21530198Sbostic 				}
21630198Sbostic 				else {
21730198Sbostic 					*value = 0;
21830198Sbostic 					--count[C_END_LIMIT];
21930198Sbostic 				}
22030198Sbostic 				break;
22130198Sbostic 			  case C_REPAIRS:	case C_SPARE:	case C_GAS:
22230198Sbostic 				safe = safety(card) - S_CONV;
22330198Sbostic 				oppos = opposite(card);
22430198Sbostic 				if (pp->safety[safe] != S_UNKNOWN)
22530198Sbostic 					*value = (pp->safety[safe] ==
22630198Sbostic 						  S_PLAYED ? -1 : 1);
22730198Sbostic 				else if (pp->battle != oppos
22830198Sbostic 				    && (Numseen[oppos] == Numcards[oppos] ||
22930198Sbostic 					Numseen[oppos] + count[card] >
23030198Sbostic 					Numcards[oppos])) {
23130198Sbostic 					*value = 0;
23230198Sbostic 					--count[card];
23330198Sbostic 				}
23430198Sbostic 				else {
23530198Sbostic repair:
23630198Sbostic 					*value = Numcards[oppos] * 6;
23730198Sbostic 					*value += Numseen[card] -
23830198Sbostic 						  Numseen[oppos];
23930198Sbostic 					if (!cango)
24030198Sbostic 					    *value /= (count[card]*count[card]);
24130198Sbostic 					count[card]--;
24230198Sbostic 				}
24330198Sbostic 				break;
24430198Sbostic 			  case C_GO:
24530198Sbostic 				if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN)
24630198Sbostic 					*value = (pp->safety[S_RIGHT_WAY] ==
24730198Sbostic 						  S_PLAYED ? -1 : 2);
24830198Sbostic 				else if (pp->can_go
24930198Sbostic 				 && Numgos + count[C_GO] == Numneed[C_GO]) {
25030198Sbostic 					*value = 0;
25130198Sbostic 					--count[C_GO];
25230198Sbostic 				}
25330198Sbostic 				else {
25430198Sbostic 					*value = Numneed[C_GO] * 3;
25530198Sbostic 					*value += (Numseen[C_GO] - Numgos);
25630198Sbostic 					*value /= (count[C_GO] * count[C_GO]);
25730198Sbostic 					count[C_GO]--;
25830198Sbostic 				}
25930198Sbostic 				break;
26030198Sbostic 			  case C_LIMIT:
26130198Sbostic 				if (op->mileage + 50 >= End) {
26230198Sbostic 					*value = (End == 700 && !cango);
26330198Sbostic 					break;
26430198Sbostic 				}
26530198Sbostic 				if (canstop || (cango && !op->can_go))
26630198Sbostic 					*value = 1;
26730198Sbostic 				else {
26830198Sbostic 					*value = (pp->safety[S_RIGHT_WAY] !=
26930198Sbostic 						  S_UNKNOWN ? 2 : 3);
27030198Sbostic 					safe = S_RIGHT_WAY;
27130198Sbostic 					oppos = C_END_LIMIT;
27230198Sbostic 					goto normbad;
27330198Sbostic 				}
27430198Sbostic 				break;
27530198Sbostic 			  case C_CRASH:	case C_EMPTY:	case C_FLAT:
27630198Sbostic 				safe = safety(card) - S_CONV;
27730198Sbostic 				oppos = opposite(card);
27830198Sbostic 				*value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4);
27930198Sbostic normbad:
28030198Sbostic 				if (op->safety[safe] == S_PLAYED)
28130198Sbostic 					*value = -1;
28230198Sbostic 				else {
28330198Sbostic 					*value *= Numneed[oppos] +
28430198Sbostic 						  Numseen[oppos] + 2;
28530198Sbostic 					if (!pp->mileage || foundend ||
28630198Sbostic 					    onecard(op))
28730198Sbostic 						*value += 5;
28830198Sbostic 					if (op->mileage == 0 || onecard(op))
28930198Sbostic 						*value += 5;
29030198Sbostic 					if (op->speed == C_LIMIT)
29130198Sbostic 						*value -= 3;
29230198Sbostic 					if (cango &&
29330198Sbostic 					    pp->safety[safe] != S_UNKNOWN)
29430198Sbostic 						*value += 3;
29530198Sbostic 					if (!cango)
29630198Sbostic 						*value /= ++badcount;
29730198Sbostic 				}
29830198Sbostic 				break;
29930198Sbostic 			  case C_STOP:
30030198Sbostic 				if (op->safety[S_RIGHT_WAY] == S_PLAYED)
30130198Sbostic 					*value = -1;
30230198Sbostic 				else {
30330198Sbostic 					*value = (pp->safety[S_RIGHT_WAY] !=
30430198Sbostic 						  S_UNKNOWN ? 3 : 4);
30530198Sbostic 					*value *= Numcards[C_STOP] +
30630198Sbostic 						  Numseen[C_GO];
30730198Sbostic 					if (!pp->mileage || foundend ||
30830198Sbostic 					    onecard(op))
30930198Sbostic 						*value += 5;
31030198Sbostic 					if (!cango)
31130198Sbostic 						*value /= ++badcount;
31230198Sbostic 					if (op->mileage == 0)
31330198Sbostic 						*value += 5;
31430198Sbostic 					if ((card == C_LIMIT &&
31530198Sbostic 					     op->speed == C_LIMIT) ||
31630198Sbostic 					    !op->can_go)
31730198Sbostic 						*value -= 5;
31830198Sbostic 					if (cango && pp->safety[S_RIGHT_WAY] !=
31930198Sbostic 						     S_UNKNOWN)
32030198Sbostic 						*value += 5;
32130198Sbostic 				}
32230198Sbostic 				break;
32330198Sbostic 			  case C_GAS_SAFE:	case C_DRIVE_SAFE:
32430198Sbostic 			  case C_SPARE_SAFE:	case C_RIGHT_WAY:
32530198Sbostic 				*value = cango ? 0 : 101;
32630198Sbostic 				break;
32730198Sbostic 			  case C_INIT:
32830198Sbostic 				*value = 0;
32930198Sbostic 				break;
33030198Sbostic 			}
33130198Sbostic 		}
33230198Sbostic 		else
33330198Sbostic 			*value = cango ? 0 : 101;
33430198Sbostic 		if (card != C_INIT) {
33530198Sbostic 			if (*value >= curmax) {
33630198Sbostic 				nummax = i;
33730198Sbostic 				curmax = *value;
33830198Sbostic 			}
33930198Sbostic 			if (*value <= curmin) {
34030198Sbostic 				nummin = i;
34130198Sbostic 				curmin = *value;
34230198Sbostic 			}
34330198Sbostic 		}
344*33170Sbostic #ifdef DEBUG
34530198Sbostic 		if (Debug)
34630198Sbostic 			mvprintw(i + 6, 2, "%3d %-14s", *value,
34730198Sbostic 				 C_name[pp->hand[i]]);
348*33170Sbostic #endif
34930198Sbostic 		value++;
35030198Sbostic 	}
35130198Sbostic 	if (!pp->can_go && !isrepair(pp->battle))
35230198Sbostic 		Numneed[opposite(pp->battle)]++;
35330198Sbostic 	if (cango) {
35430198Sbostic play_it:
35530198Sbostic 		mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n");
356*33170Sbostic #ifdef DEBUG
35730198Sbostic 		if (Debug)
35830198Sbostic 			getmove();
35930198Sbostic 		if (!Debug || Movetype == M_DRAW) {
360*33170Sbostic #else
361*33170Sbostic 		if (Movetype == M_DRAW) {
362*33170Sbostic #endif
36330198Sbostic 			Movetype = M_PLAY;
36430198Sbostic 			Card_no = nummax;
36530198Sbostic 		}
36630198Sbostic 	}
36730198Sbostic 	else {
36830198Sbostic 		if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */
36930198Sbostic 			nummax = nummin;
37030198Sbostic 			goto play_it;
37130198Sbostic 		}
37230198Sbostic 		mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n");
373*33170Sbostic #ifdef DEBUG
37430198Sbostic 		if (Debug)
37530198Sbostic 			getmove();
37630198Sbostic 		if (!Debug || Movetype == M_DRAW) {
377*33170Sbostic #else
378*33170Sbostic 		if (Movetype == M_DRAW) {
379*33170Sbostic #endif
38030198Sbostic 			Movetype = M_DISCARD;
38130198Sbostic 			Card_no = nummin;
38230198Sbostic 		}
38330198Sbostic 	}
38430198Sbostic 	mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]);
38530198Sbostic }
38630198Sbostic 
38730198Sbostic onecard(pp)
38830198Sbostic register PLAY	*pp;
38930198Sbostic {
39030198Sbostic 	register CARD	bat, spd, card;
39130198Sbostic 
39230198Sbostic 	bat = pp->battle;
39330198Sbostic 	spd = pp->speed;
39430198Sbostic 	card = -1;
39530198Sbostic 	if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) &&
39630198Sbostic 			   Numseen[S_RIGHT_WAY] != 0) ||
39730198Sbostic 	    Numseen[safety(bat)] != 0)
39830198Sbostic 		switch (End - pp->mileage) {
39930198Sbostic 		  case 200:
40030198Sbostic 			if (pp->nummiles[C_200] == 2)
40130198Sbostic 				return FALSE;
40230198Sbostic 			card = C_200;
40330198Sbostic 			/* FALLTHROUGH */
40430198Sbostic 		  case 100:
40530198Sbostic 		  case 75:
40630198Sbostic 			if (card == -1)
40730198Sbostic 				card = (End - pp->mileage == 75 ? C_75 : C_100);
40830198Sbostic 			if (spd == C_LIMIT)
40930198Sbostic 				return Numseen[S_RIGHT_WAY] == 0;
41030198Sbostic 		  case 50:
41130198Sbostic 		  case 25:
41230198Sbostic 			if (card == -1)
41330198Sbostic 				card = (End - pp->mileage == 25 ? C_25 : C_50);
41430198Sbostic 			return Numseen[card] != Numcards[card];
41530198Sbostic 		}
41630198Sbostic 	return FALSE;
41730198Sbostic }
41830198Sbostic 
41930198Sbostic canplay(pp, op, card)
42030198Sbostic register PLAY	*pp, *op;
42130198Sbostic register CARD	card;
42230198Sbostic {
42330198Sbostic 	switch (card) {
42430198Sbostic 	  case C_200:
42530198Sbostic 		if (pp->nummiles[C_200] == 2)
42630198Sbostic 			break;
42730198Sbostic 		/* FALLTHROUGH */
42830198Sbostic 	  case C_75:	case C_100:
42930198Sbostic 		if (pp->speed == C_LIMIT)
43030198Sbostic 			break;
43130198Sbostic 		/* FALLTHROUGH */
43230198Sbostic 	  case C_50:
43330198Sbostic 		if (pp->mileage + Value[card] > End)
43430198Sbostic 			break;
43530198Sbostic 		/* FALLTHROUGH */
43630198Sbostic 	  case C_25:
43730198Sbostic 		if (pp->can_go)
43830198Sbostic 			return TRUE;
43930198Sbostic 		break;
44030198Sbostic 	  case C_EMPTY:	case C_FLAT:	case C_CRASH:
44130198Sbostic 	  case C_STOP:
44230198Sbostic 		if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED)
44330198Sbostic 			return TRUE;
44430198Sbostic 		break;
44530198Sbostic 	  case C_LIMIT:
44630198Sbostic 		if (op->speed != C_LIMIT &&
44730198Sbostic 		    op->safety[S_RIGHT_WAY] != S_PLAYED &&
44830198Sbostic 		    op->mileage + 50 < End)
44930198Sbostic 			return TRUE;
45030198Sbostic 		break;
45130198Sbostic 	  case C_GAS:	case C_SPARE:	case C_REPAIRS:
45230198Sbostic 		if (pp->battle == opposite(card))
45330198Sbostic 			return TRUE;
45430198Sbostic 		break;
45530198Sbostic 	  case C_GO:
45630198Sbostic 		if (!pp->can_go &&
45730198Sbostic 		    (isrepair(pp->battle) || pp->battle == C_STOP))
45830198Sbostic 			return TRUE;
45930198Sbostic 		break;
46030198Sbostic 	  case C_END_LIMIT:
46130198Sbostic 		if (pp->speed == C_LIMIT)
46230198Sbostic 			return TRUE;
46330198Sbostic 	}
46430198Sbostic 	return FALSE;
46530198Sbostic }
466