130198Sbostic /* 230198Sbostic * Copyright (c) 1982 Regents of the University of California. 333170Sbostic * All rights reserved. 433170Sbostic * 542578Sbostic * %sccs.include.redist.c% 630198Sbostic */ 730198Sbostic 830198Sbostic #ifndef lint 9*52876Storek static char sccsid[] = "@(#)comp.c 5.6 (Berkeley) 03/08/92"; 1033170Sbostic #endif /* not lint */ 1130198Sbostic 1230198Sbostic # include "mille.h" 1330198Sbostic 1430198Sbostic /* 1530198Sbostic * @(#)comp.c 1.1 (Berkeley) 4/1/82 1630198Sbostic */ 1730198Sbostic 1830198Sbostic # define V_VALUABLE 40 1930198Sbostic 2030198Sbostic calcmove() 2130198Sbostic { 2230198Sbostic register CARD card; 2330198Sbostic register int *value; 2430198Sbostic register PLAY *pp, *op; 2530198Sbostic register bool foundend, cango, canstop, foundlow; 2630198Sbostic register unsgn int i, count200, badcount, nummin, nummax, diff; 2730198Sbostic register int curmin, curmax; 2830198Sbostic register CARD safe, oppos; 2930198Sbostic int valbuf[HAND_SZ], count[NUM_CARDS]; 3030198Sbostic bool playit[HAND_SZ]; 3130198Sbostic 3230198Sbostic wmove(Score, ERR_Y, ERR_X); /* get rid of error messages */ 3330198Sbostic wclrtoeol(Score); 3430198Sbostic pp = &Player[COMP]; 3530198Sbostic op = &Player[PLAYER]; 3630198Sbostic safe = 0; 3730198Sbostic cango = 0; 3830198Sbostic canstop = FALSE; 3930198Sbostic foundend = FALSE; 40*52876Storek 41*52876Storek /* Try for a Coup Forre, and see what we have. */ 4230198Sbostic for (i = 0; i < NUM_CARDS; i++) 4330198Sbostic count[i] = 0; 4430198Sbostic for (i = 0; i < HAND_SZ; i++) { 4530198Sbostic card = pp->hand[i]; 4630198Sbostic switch (card) { 4730198Sbostic case C_STOP: case C_CRASH: 4830198Sbostic case C_FLAT: case C_EMPTY: 4930198Sbostic if (playit[i] = canplay(pp, op, card)) 5030198Sbostic canstop = TRUE; 5130198Sbostic goto norm; 5230198Sbostic case C_LIMIT: 5330198Sbostic if ((playit[i] = canplay(pp, op, card)) 5430198Sbostic && Numseen[C_25] == Numcards[C_25] 5530198Sbostic && Numseen[C_50] == Numcards[C_50]) 5630198Sbostic canstop = TRUE; 5730198Sbostic goto norm; 5830198Sbostic case C_25: case C_50: case C_75: 5930198Sbostic case C_100: case C_200: 6030198Sbostic if ((playit[i] = canplay(pp, op, card)) 6130198Sbostic && pp->mileage + Value[card] == End) 6230198Sbostic foundend = TRUE; 6330198Sbostic goto norm; 6430198Sbostic default: 6530198Sbostic playit[i] = canplay(pp, op, card); 6630198Sbostic norm: 6730198Sbostic if (playit[i]) 6830198Sbostic ++cango; 6930198Sbostic break; 7030198Sbostic case C_GAS_SAFE: case C_DRIVE_SAFE: 7130198Sbostic case C_SPARE_SAFE: case C_RIGHT_WAY: 7230198Sbostic if (pp->battle == opposite(card) || 7330198Sbostic (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) { 7430198Sbostic Movetype = M_PLAY; 7530198Sbostic Card_no = i; 7630198Sbostic return; 7730198Sbostic } 7830198Sbostic ++safe; 7930198Sbostic playit[i] = TRUE; 8030198Sbostic break; 8130198Sbostic } 82*52876Storek if (card >= 0) 83*52876Storek ++count[card]; 8430198Sbostic } 85*52876Storek 86*52876Storek /* No Coup Forre. Draw to fill hand, then restart, as needed. */ 8730198Sbostic if (pp->hand[0] == C_INIT && Topcard > Deck) { 8830198Sbostic Movetype = M_DRAW; 8930198Sbostic return; 9030198Sbostic } 91*52876Storek 9233170Sbostic #ifdef DEBUG 9330198Sbostic if (Debug) 9430198Sbostic fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n", 9530198Sbostic cango, canstop, safe); 9633170Sbostic #endif 9730198Sbostic if (foundend) 9830198Sbostic foundend = !check_ext(TRUE); 9930198Sbostic for (i = 0; safe && i < HAND_SZ; i++) { 10030198Sbostic if (issafety(pp->hand[i])) { 10130198Sbostic if (onecard(op) || (foundend && cango && !canstop)) { 10233170Sbostic #ifdef DEBUG 10330198Sbostic if (Debug) 10430198Sbostic fprintf(outf, 10530198Sbostic "CALCMOVE: onecard(op) = %d, foundend = %d\n", 10630198Sbostic onecard(op), foundend); 10733170Sbostic #endif 10830198Sbostic playsafe: 10930198Sbostic Movetype = M_PLAY; 11030198Sbostic Card_no = i; 11130198Sbostic return; 11230198Sbostic } 11330198Sbostic oppos = opposite(pp->hand[i]); 11430198Sbostic if (Numseen[oppos] == Numcards[oppos] && 11530198Sbostic !(pp->hand[i] == C_RIGHT_WAY && 11630198Sbostic Numseen[C_LIMIT] != Numcards[C_LIMIT])) 11730198Sbostic goto playsafe; 11830198Sbostic else if (!cango 11930198Sbostic && (op->can_go || !pp->can_go || Topcard < Deck)) { 12030198Sbostic card = (Topcard - Deck) - roll(1, 10); 12130198Sbostic if ((!pp->mileage) != (!op->mileage)) 12230198Sbostic card -= 7; 12333170Sbostic #ifdef DEBUG 12430198Sbostic if (Debug) 12530198Sbostic fprintf(outf, 12630198Sbostic "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n", 12730198Sbostic card, DECK_SZ / 4); 12833170Sbostic #endif 12930198Sbostic if (card < DECK_SZ / 4) 13030198Sbostic goto playsafe; 13130198Sbostic } 13230198Sbostic safe--; 13330198Sbostic playit[i] = cango; 13430198Sbostic } 13530198Sbostic } 13630198Sbostic if (!pp->can_go && !isrepair(pp->battle)) 13730198Sbostic Numneed[opposite(pp->battle)]++; 13830198Sbostic redoit: 13930198Sbostic foundlow = (cango || count[C_END_LIMIT] != 0 14030198Sbostic || Numseen[C_LIMIT] == Numcards[C_LIMIT] 14130198Sbostic || pp->safety[S_RIGHT_WAY] != S_UNKNOWN); 14230198Sbostic foundend = FALSE; 14330198Sbostic count200 = pp->nummiles[C_200]; 14430198Sbostic badcount = 0; 14530198Sbostic curmax = -1; 14630198Sbostic curmin = 101; 14730198Sbostic nummin = -1; 14830198Sbostic nummax = -1; 14930198Sbostic value = valbuf; 15030198Sbostic for (i = 0; i < HAND_SZ; i++) { 15130198Sbostic card = pp->hand[i]; 15230198Sbostic if (issafety(card) || playit[i] == (cango != 0)) { 15333170Sbostic #ifdef DEBUG 15430198Sbostic if (Debug) 15530198Sbostic fprintf(outf, "CALCMOVE: switch(\"%s\")\n", 15630198Sbostic C_name[card]); 15733170Sbostic #endif 15830198Sbostic switch (card) { 15930198Sbostic case C_25: case C_50: 16030198Sbostic diff = End - pp->mileage; 16130198Sbostic /* avoid getting too close */ 16230198Sbostic if (Topcard > Deck && cango && diff <= 100 16330198Sbostic && diff / Value[card] > count[card] 16430198Sbostic && (card == C_25 || diff % 50 == 0)) { 16530198Sbostic if (card == C_50 && diff - 50 == 25 16630198Sbostic && count[C_25] > 0) 16730198Sbostic goto okay; 16830198Sbostic *value = 0; 16930198Sbostic if (--cango <= 0) 17030198Sbostic goto redoit; 17130198Sbostic break; 17230198Sbostic } 17330198Sbostic okay: 17430198Sbostic *value = (Value[card] >> 3); 17530198Sbostic if (pp->speed == C_LIMIT) 17630198Sbostic ++*value; 17730198Sbostic else 17830198Sbostic --*value; 17930198Sbostic if (!foundlow 18030198Sbostic && (card == C_50 || count[C_50] == 0)) { 18130198Sbostic *value = (pp->mileage ? 10 : 20); 18230198Sbostic foundlow = TRUE; 18330198Sbostic } 18430198Sbostic goto miles; 18530198Sbostic case C_200: 18630198Sbostic if (++count200 > 2) { 18730198Sbostic *value = 0; 18830198Sbostic break; 18930198Sbostic } 19030198Sbostic case C_75: case C_100: 19130198Sbostic *value = (Value[card] >> 3); 19230198Sbostic if (pp->speed == C_LIMIT) 19330198Sbostic --*value; 19430198Sbostic else 19530198Sbostic ++*value; 19630198Sbostic miles: 19730198Sbostic if (pp->mileage + Value[card] > End) 19830198Sbostic *value = (End == 700 ? card : 0); 19930198Sbostic else if (pp->mileage + Value[card] == End) { 20030198Sbostic *value = (foundend ? card : V_VALUABLE); 20130198Sbostic foundend = TRUE; 20230198Sbostic } 20330198Sbostic break; 20430198Sbostic case C_END_LIMIT: 20530198Sbostic if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN) 20630198Sbostic *value = (pp->safety[S_RIGHT_WAY] == 20730198Sbostic S_PLAYED ? -1 : 1); 20830198Sbostic else if (pp->speed == C_LIMIT && 20930198Sbostic End - pp->mileage <= 50) 21030198Sbostic *value = 1; 21130198Sbostic else if (pp->speed == C_LIMIT 21230198Sbostic || Numseen[C_LIMIT] != Numcards[C_LIMIT]) { 21330198Sbostic safe = S_RIGHT_WAY; 21430198Sbostic oppos = C_LIMIT; 21530198Sbostic goto repair; 21630198Sbostic } 21730198Sbostic else { 21830198Sbostic *value = 0; 21930198Sbostic --count[C_END_LIMIT]; 22030198Sbostic } 22130198Sbostic break; 22230198Sbostic case C_REPAIRS: case C_SPARE: case C_GAS: 22330198Sbostic safe = safety(card) - S_CONV; 22430198Sbostic oppos = opposite(card); 22530198Sbostic if (pp->safety[safe] != S_UNKNOWN) 22630198Sbostic *value = (pp->safety[safe] == 22730198Sbostic S_PLAYED ? -1 : 1); 22830198Sbostic else if (pp->battle != oppos 22930198Sbostic && (Numseen[oppos] == Numcards[oppos] || 23030198Sbostic Numseen[oppos] + count[card] > 23130198Sbostic Numcards[oppos])) { 23230198Sbostic *value = 0; 23330198Sbostic --count[card]; 23430198Sbostic } 23530198Sbostic else { 23630198Sbostic repair: 23730198Sbostic *value = Numcards[oppos] * 6; 23830198Sbostic *value += Numseen[card] - 23930198Sbostic Numseen[oppos]; 24030198Sbostic if (!cango) 24130198Sbostic *value /= (count[card]*count[card]); 24230198Sbostic count[card]--; 24330198Sbostic } 24430198Sbostic break; 24530198Sbostic case C_GO: 24630198Sbostic if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN) 24730198Sbostic *value = (pp->safety[S_RIGHT_WAY] == 24830198Sbostic S_PLAYED ? -1 : 2); 24930198Sbostic else if (pp->can_go 25030198Sbostic && Numgos + count[C_GO] == Numneed[C_GO]) { 25130198Sbostic *value = 0; 25230198Sbostic --count[C_GO]; 25330198Sbostic } 25430198Sbostic else { 25530198Sbostic *value = Numneed[C_GO] * 3; 25630198Sbostic *value += (Numseen[C_GO] - Numgos); 25730198Sbostic *value /= (count[C_GO] * count[C_GO]); 25830198Sbostic count[C_GO]--; 25930198Sbostic } 26030198Sbostic break; 26130198Sbostic case C_LIMIT: 26230198Sbostic if (op->mileage + 50 >= End) { 26330198Sbostic *value = (End == 700 && !cango); 26430198Sbostic break; 26530198Sbostic } 26630198Sbostic if (canstop || (cango && !op->can_go)) 26730198Sbostic *value = 1; 26830198Sbostic else { 26930198Sbostic *value = (pp->safety[S_RIGHT_WAY] != 27030198Sbostic S_UNKNOWN ? 2 : 3); 27130198Sbostic safe = S_RIGHT_WAY; 27230198Sbostic oppos = C_END_LIMIT; 27330198Sbostic goto normbad; 27430198Sbostic } 27530198Sbostic break; 27630198Sbostic case C_CRASH: case C_EMPTY: case C_FLAT: 27730198Sbostic safe = safety(card) - S_CONV; 27830198Sbostic oppos = opposite(card); 27930198Sbostic *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4); 28030198Sbostic normbad: 28130198Sbostic if (op->safety[safe] == S_PLAYED) 28230198Sbostic *value = -1; 28330198Sbostic else { 28430198Sbostic *value *= Numneed[oppos] + 28530198Sbostic Numseen[oppos] + 2; 28630198Sbostic if (!pp->mileage || foundend || 28730198Sbostic onecard(op)) 28830198Sbostic *value += 5; 28930198Sbostic if (op->mileage == 0 || onecard(op)) 29030198Sbostic *value += 5; 29130198Sbostic if (op->speed == C_LIMIT) 29230198Sbostic *value -= 3; 29330198Sbostic if (cango && 29430198Sbostic pp->safety[safe] != S_UNKNOWN) 29530198Sbostic *value += 3; 29630198Sbostic if (!cango) 29730198Sbostic *value /= ++badcount; 29830198Sbostic } 29930198Sbostic break; 30030198Sbostic case C_STOP: 30130198Sbostic if (op->safety[S_RIGHT_WAY] == S_PLAYED) 30230198Sbostic *value = -1; 30330198Sbostic else { 30430198Sbostic *value = (pp->safety[S_RIGHT_WAY] != 30530198Sbostic S_UNKNOWN ? 3 : 4); 30630198Sbostic *value *= Numcards[C_STOP] + 30730198Sbostic Numseen[C_GO]; 30830198Sbostic if (!pp->mileage || foundend || 30930198Sbostic onecard(op)) 31030198Sbostic *value += 5; 31130198Sbostic if (!cango) 31230198Sbostic *value /= ++badcount; 31330198Sbostic if (op->mileage == 0) 31430198Sbostic *value += 5; 31530198Sbostic if ((card == C_LIMIT && 31630198Sbostic op->speed == C_LIMIT) || 31730198Sbostic !op->can_go) 31830198Sbostic *value -= 5; 31930198Sbostic if (cango && pp->safety[S_RIGHT_WAY] != 32030198Sbostic S_UNKNOWN) 32130198Sbostic *value += 5; 32230198Sbostic } 32330198Sbostic break; 32430198Sbostic case C_GAS_SAFE: case C_DRIVE_SAFE: 32530198Sbostic case C_SPARE_SAFE: case C_RIGHT_WAY: 32630198Sbostic *value = cango ? 0 : 101; 32730198Sbostic break; 32830198Sbostic case C_INIT: 32930198Sbostic *value = 0; 33030198Sbostic break; 33130198Sbostic } 33230198Sbostic } 33330198Sbostic else 33430198Sbostic *value = cango ? 0 : 101; 33530198Sbostic if (card != C_INIT) { 33630198Sbostic if (*value >= curmax) { 33730198Sbostic nummax = i; 33830198Sbostic curmax = *value; 33930198Sbostic } 34030198Sbostic if (*value <= curmin) { 34130198Sbostic nummin = i; 34230198Sbostic curmin = *value; 34330198Sbostic } 34430198Sbostic } 34533170Sbostic #ifdef DEBUG 34630198Sbostic if (Debug) 34730198Sbostic mvprintw(i + 6, 2, "%3d %-14s", *value, 34830198Sbostic C_name[pp->hand[i]]); 34933170Sbostic #endif 35030198Sbostic value++; 35130198Sbostic } 35230198Sbostic if (!pp->can_go && !isrepair(pp->battle)) 35330198Sbostic Numneed[opposite(pp->battle)]++; 35430198Sbostic if (cango) { 35530198Sbostic play_it: 35630198Sbostic mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n"); 357*52876Storek Movetype = M_PLAY; 358*52876Storek Card_no = nummax; 35930198Sbostic } 36030198Sbostic else { 36130198Sbostic if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */ 36230198Sbostic nummax = nummin; 36330198Sbostic goto play_it; 36430198Sbostic } 36530198Sbostic mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n"); 366*52876Storek Movetype = M_DISCARD; 367*52876Storek Card_no = nummin; 36830198Sbostic } 36930198Sbostic mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]); 37030198Sbostic } 37130198Sbostic 372*52876Storek /* 373*52876Storek * Return true if the given player could conceivably win with his next card. 374*52876Storek */ 37530198Sbostic onecard(pp) 37630198Sbostic register PLAY *pp; 37730198Sbostic { 37830198Sbostic register CARD bat, spd, card; 37930198Sbostic 38030198Sbostic bat = pp->battle; 38130198Sbostic spd = pp->speed; 38230198Sbostic card = -1; 38330198Sbostic if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) && 38430198Sbostic Numseen[S_RIGHT_WAY] != 0) || 38552872Storek bat >= 0 && Numseen[safety(bat)] != 0) 38630198Sbostic switch (End - pp->mileage) { 38730198Sbostic case 200: 38830198Sbostic if (pp->nummiles[C_200] == 2) 38930198Sbostic return FALSE; 39030198Sbostic card = C_200; 39130198Sbostic /* FALLTHROUGH */ 39230198Sbostic case 100: 39330198Sbostic case 75: 39430198Sbostic if (card == -1) 39530198Sbostic card = (End - pp->mileage == 75 ? C_75 : C_100); 39630198Sbostic if (spd == C_LIMIT) 39730198Sbostic return Numseen[S_RIGHT_WAY] == 0; 39830198Sbostic case 50: 39930198Sbostic case 25: 40030198Sbostic if (card == -1) 40130198Sbostic card = (End - pp->mileage == 25 ? C_25 : C_50); 40230198Sbostic return Numseen[card] != Numcards[card]; 40330198Sbostic } 40430198Sbostic return FALSE; 40530198Sbostic } 40630198Sbostic 40730198Sbostic canplay(pp, op, card) 40830198Sbostic register PLAY *pp, *op; 40930198Sbostic register CARD card; 41030198Sbostic { 41130198Sbostic switch (card) { 41230198Sbostic case C_200: 41330198Sbostic if (pp->nummiles[C_200] == 2) 41430198Sbostic break; 41530198Sbostic /* FALLTHROUGH */ 41630198Sbostic case C_75: case C_100: 41730198Sbostic if (pp->speed == C_LIMIT) 41830198Sbostic break; 41930198Sbostic /* FALLTHROUGH */ 42030198Sbostic case C_50: 42130198Sbostic if (pp->mileage + Value[card] > End) 42230198Sbostic break; 42330198Sbostic /* FALLTHROUGH */ 42430198Sbostic case C_25: 42530198Sbostic if (pp->can_go) 42630198Sbostic return TRUE; 42730198Sbostic break; 42830198Sbostic case C_EMPTY: case C_FLAT: case C_CRASH: 42930198Sbostic case C_STOP: 43030198Sbostic if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED) 43130198Sbostic return TRUE; 43230198Sbostic break; 43330198Sbostic case C_LIMIT: 43430198Sbostic if (op->speed != C_LIMIT && 43530198Sbostic op->safety[S_RIGHT_WAY] != S_PLAYED && 43630198Sbostic op->mileage + 50 < End) 43730198Sbostic return TRUE; 43830198Sbostic break; 43930198Sbostic case C_GAS: case C_SPARE: case C_REPAIRS: 44030198Sbostic if (pp->battle == opposite(card)) 44130198Sbostic return TRUE; 44230198Sbostic break; 44330198Sbostic case C_GO: 44430198Sbostic if (!pp->can_go && 44530198Sbostic (isrepair(pp->battle) || pp->battle == C_STOP)) 44630198Sbostic return TRUE; 44730198Sbostic break; 44830198Sbostic case C_END_LIMIT: 44930198Sbostic if (pp->speed == C_LIMIT) 45030198Sbostic return TRUE; 45130198Sbostic } 45230198Sbostic return FALSE; 45330198Sbostic } 454