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*52872Storek static char sccsid[] = "@(#)comp.c 5.5 (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; 4030198Sbostic for (i = 0; i < NUM_CARDS; i++) 4130198Sbostic count[i] = 0; 4230198Sbostic for (i = 0; i < HAND_SZ; i++) { 4330198Sbostic card = pp->hand[i]; 4430198Sbostic switch (card) { 4530198Sbostic case C_STOP: case C_CRASH: 4630198Sbostic case C_FLAT: case C_EMPTY: 4730198Sbostic if (playit[i] = canplay(pp, op, card)) 4830198Sbostic canstop = TRUE; 4930198Sbostic goto norm; 5030198Sbostic case C_LIMIT: 5130198Sbostic if ((playit[i] = canplay(pp, op, card)) 5230198Sbostic && Numseen[C_25] == Numcards[C_25] 5330198Sbostic && Numseen[C_50] == Numcards[C_50]) 5430198Sbostic canstop = TRUE; 5530198Sbostic goto norm; 5630198Sbostic case C_25: case C_50: case C_75: 5730198Sbostic case C_100: case C_200: 5830198Sbostic if ((playit[i] = canplay(pp, op, card)) 5930198Sbostic && pp->mileage + Value[card] == End) 6030198Sbostic foundend = TRUE; 6130198Sbostic goto norm; 6230198Sbostic default: 6330198Sbostic playit[i] = canplay(pp, op, card); 6430198Sbostic norm: 6530198Sbostic if (playit[i]) 6630198Sbostic ++cango; 6730198Sbostic break; 6830198Sbostic case C_GAS_SAFE: case C_DRIVE_SAFE: 6930198Sbostic case C_SPARE_SAFE: case C_RIGHT_WAY: 7030198Sbostic if (pp->battle == opposite(card) || 7130198Sbostic (pp->speed == C_LIMIT && card == C_RIGHT_WAY)) { 7230198Sbostic Movetype = M_PLAY; 7330198Sbostic Card_no = i; 7430198Sbostic return; 7530198Sbostic } 7630198Sbostic ++safe; 7730198Sbostic playit[i] = TRUE; 7830198Sbostic break; 7930198Sbostic } 8030198Sbostic ++count[card]; 8130198Sbostic } 8230198Sbostic if (pp->hand[0] == C_INIT && Topcard > Deck) { 8330198Sbostic Movetype = M_DRAW; 8430198Sbostic return; 8530198Sbostic } 8633170Sbostic #ifdef DEBUG 8730198Sbostic if (Debug) 8830198Sbostic fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n", 8930198Sbostic cango, canstop, safe); 9033170Sbostic #endif 9130198Sbostic if (foundend) 9230198Sbostic foundend = !check_ext(TRUE); 9330198Sbostic for (i = 0; safe && i < HAND_SZ; i++) { 9430198Sbostic if (issafety(pp->hand[i])) { 9530198Sbostic if (onecard(op) || (foundend && cango && !canstop)) { 9633170Sbostic #ifdef DEBUG 9730198Sbostic if (Debug) 9830198Sbostic fprintf(outf, 9930198Sbostic "CALCMOVE: onecard(op) = %d, foundend = %d\n", 10030198Sbostic onecard(op), foundend); 10133170Sbostic #endif 10230198Sbostic playsafe: 10330198Sbostic Movetype = M_PLAY; 10430198Sbostic Card_no = i; 10530198Sbostic return; 10630198Sbostic } 10730198Sbostic oppos = opposite(pp->hand[i]); 10830198Sbostic if (Numseen[oppos] == Numcards[oppos] && 10930198Sbostic !(pp->hand[i] == C_RIGHT_WAY && 11030198Sbostic Numseen[C_LIMIT] != Numcards[C_LIMIT])) 11130198Sbostic goto playsafe; 11230198Sbostic else if (!cango 11330198Sbostic && (op->can_go || !pp->can_go || Topcard < Deck)) { 11430198Sbostic card = (Topcard - Deck) - roll(1, 10); 11530198Sbostic if ((!pp->mileage) != (!op->mileage)) 11630198Sbostic card -= 7; 11733170Sbostic #ifdef DEBUG 11830198Sbostic if (Debug) 11930198Sbostic fprintf(outf, 12030198Sbostic "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n", 12130198Sbostic card, DECK_SZ / 4); 12233170Sbostic #endif 12330198Sbostic if (card < DECK_SZ / 4) 12430198Sbostic goto playsafe; 12530198Sbostic } 12630198Sbostic safe--; 12730198Sbostic playit[i] = cango; 12830198Sbostic } 12930198Sbostic } 13030198Sbostic if (!pp->can_go && !isrepair(pp->battle)) 13130198Sbostic Numneed[opposite(pp->battle)]++; 13230198Sbostic redoit: 13330198Sbostic foundlow = (cango || count[C_END_LIMIT] != 0 13430198Sbostic || Numseen[C_LIMIT] == Numcards[C_LIMIT] 13530198Sbostic || pp->safety[S_RIGHT_WAY] != S_UNKNOWN); 13630198Sbostic foundend = FALSE; 13730198Sbostic count200 = pp->nummiles[C_200]; 13830198Sbostic badcount = 0; 13930198Sbostic curmax = -1; 14030198Sbostic curmin = 101; 14130198Sbostic nummin = -1; 14230198Sbostic nummax = -1; 14330198Sbostic value = valbuf; 14430198Sbostic for (i = 0; i < HAND_SZ; i++) { 14530198Sbostic card = pp->hand[i]; 14630198Sbostic if (issafety(card) || playit[i] == (cango != 0)) { 14733170Sbostic #ifdef DEBUG 14830198Sbostic if (Debug) 14930198Sbostic fprintf(outf, "CALCMOVE: switch(\"%s\")\n", 15030198Sbostic C_name[card]); 15133170Sbostic #endif 15230198Sbostic switch (card) { 15330198Sbostic case C_25: case C_50: 15430198Sbostic diff = End - pp->mileage; 15530198Sbostic /* avoid getting too close */ 15630198Sbostic if (Topcard > Deck && cango && diff <= 100 15730198Sbostic && diff / Value[card] > count[card] 15830198Sbostic && (card == C_25 || diff % 50 == 0)) { 15930198Sbostic if (card == C_50 && diff - 50 == 25 16030198Sbostic && count[C_25] > 0) 16130198Sbostic goto okay; 16230198Sbostic *value = 0; 16330198Sbostic if (--cango <= 0) 16430198Sbostic goto redoit; 16530198Sbostic break; 16630198Sbostic } 16730198Sbostic okay: 16830198Sbostic *value = (Value[card] >> 3); 16930198Sbostic if (pp->speed == C_LIMIT) 17030198Sbostic ++*value; 17130198Sbostic else 17230198Sbostic --*value; 17330198Sbostic if (!foundlow 17430198Sbostic && (card == C_50 || count[C_50] == 0)) { 17530198Sbostic *value = (pp->mileage ? 10 : 20); 17630198Sbostic foundlow = TRUE; 17730198Sbostic } 17830198Sbostic goto miles; 17930198Sbostic case C_200: 18030198Sbostic if (++count200 > 2) { 18130198Sbostic *value = 0; 18230198Sbostic break; 18330198Sbostic } 18430198Sbostic case C_75: case C_100: 18530198Sbostic *value = (Value[card] >> 3); 18630198Sbostic if (pp->speed == C_LIMIT) 18730198Sbostic --*value; 18830198Sbostic else 18930198Sbostic ++*value; 19030198Sbostic miles: 19130198Sbostic if (pp->mileage + Value[card] > End) 19230198Sbostic *value = (End == 700 ? card : 0); 19330198Sbostic else if (pp->mileage + Value[card] == End) { 19430198Sbostic *value = (foundend ? card : V_VALUABLE); 19530198Sbostic foundend = TRUE; 19630198Sbostic } 19730198Sbostic break; 19830198Sbostic case C_END_LIMIT: 19930198Sbostic if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN) 20030198Sbostic *value = (pp->safety[S_RIGHT_WAY] == 20130198Sbostic S_PLAYED ? -1 : 1); 20230198Sbostic else if (pp->speed == C_LIMIT && 20330198Sbostic End - pp->mileage <= 50) 20430198Sbostic *value = 1; 20530198Sbostic else if (pp->speed == C_LIMIT 20630198Sbostic || Numseen[C_LIMIT] != Numcards[C_LIMIT]) { 20730198Sbostic safe = S_RIGHT_WAY; 20830198Sbostic oppos = C_LIMIT; 20930198Sbostic goto repair; 21030198Sbostic } 21130198Sbostic else { 21230198Sbostic *value = 0; 21330198Sbostic --count[C_END_LIMIT]; 21430198Sbostic } 21530198Sbostic break; 21630198Sbostic case C_REPAIRS: case C_SPARE: case C_GAS: 21730198Sbostic safe = safety(card) - S_CONV; 21830198Sbostic oppos = opposite(card); 21930198Sbostic if (pp->safety[safe] != S_UNKNOWN) 22030198Sbostic *value = (pp->safety[safe] == 22130198Sbostic S_PLAYED ? -1 : 1); 22230198Sbostic else if (pp->battle != oppos 22330198Sbostic && (Numseen[oppos] == Numcards[oppos] || 22430198Sbostic Numseen[oppos] + count[card] > 22530198Sbostic Numcards[oppos])) { 22630198Sbostic *value = 0; 22730198Sbostic --count[card]; 22830198Sbostic } 22930198Sbostic else { 23030198Sbostic repair: 23130198Sbostic *value = Numcards[oppos] * 6; 23230198Sbostic *value += Numseen[card] - 23330198Sbostic Numseen[oppos]; 23430198Sbostic if (!cango) 23530198Sbostic *value /= (count[card]*count[card]); 23630198Sbostic count[card]--; 23730198Sbostic } 23830198Sbostic break; 23930198Sbostic case C_GO: 24030198Sbostic if (pp->safety[S_RIGHT_WAY] != S_UNKNOWN) 24130198Sbostic *value = (pp->safety[S_RIGHT_WAY] == 24230198Sbostic S_PLAYED ? -1 : 2); 24330198Sbostic else if (pp->can_go 24430198Sbostic && Numgos + count[C_GO] == Numneed[C_GO]) { 24530198Sbostic *value = 0; 24630198Sbostic --count[C_GO]; 24730198Sbostic } 24830198Sbostic else { 24930198Sbostic *value = Numneed[C_GO] * 3; 25030198Sbostic *value += (Numseen[C_GO] - Numgos); 25130198Sbostic *value /= (count[C_GO] * count[C_GO]); 25230198Sbostic count[C_GO]--; 25330198Sbostic } 25430198Sbostic break; 25530198Sbostic case C_LIMIT: 25630198Sbostic if (op->mileage + 50 >= End) { 25730198Sbostic *value = (End == 700 && !cango); 25830198Sbostic break; 25930198Sbostic } 26030198Sbostic if (canstop || (cango && !op->can_go)) 26130198Sbostic *value = 1; 26230198Sbostic else { 26330198Sbostic *value = (pp->safety[S_RIGHT_WAY] != 26430198Sbostic S_UNKNOWN ? 2 : 3); 26530198Sbostic safe = S_RIGHT_WAY; 26630198Sbostic oppos = C_END_LIMIT; 26730198Sbostic goto normbad; 26830198Sbostic } 26930198Sbostic break; 27030198Sbostic case C_CRASH: case C_EMPTY: case C_FLAT: 27130198Sbostic safe = safety(card) - S_CONV; 27230198Sbostic oppos = opposite(card); 27330198Sbostic *value = (pp->safety[safe]!=S_UNKNOWN ? 3 : 4); 27430198Sbostic normbad: 27530198Sbostic if (op->safety[safe] == S_PLAYED) 27630198Sbostic *value = -1; 27730198Sbostic else { 27830198Sbostic *value *= Numneed[oppos] + 27930198Sbostic Numseen[oppos] + 2; 28030198Sbostic if (!pp->mileage || foundend || 28130198Sbostic onecard(op)) 28230198Sbostic *value += 5; 28330198Sbostic if (op->mileage == 0 || onecard(op)) 28430198Sbostic *value += 5; 28530198Sbostic if (op->speed == C_LIMIT) 28630198Sbostic *value -= 3; 28730198Sbostic if (cango && 28830198Sbostic pp->safety[safe] != S_UNKNOWN) 28930198Sbostic *value += 3; 29030198Sbostic if (!cango) 29130198Sbostic *value /= ++badcount; 29230198Sbostic } 29330198Sbostic break; 29430198Sbostic case C_STOP: 29530198Sbostic if (op->safety[S_RIGHT_WAY] == S_PLAYED) 29630198Sbostic *value = -1; 29730198Sbostic else { 29830198Sbostic *value = (pp->safety[S_RIGHT_WAY] != 29930198Sbostic S_UNKNOWN ? 3 : 4); 30030198Sbostic *value *= Numcards[C_STOP] + 30130198Sbostic Numseen[C_GO]; 30230198Sbostic if (!pp->mileage || foundend || 30330198Sbostic onecard(op)) 30430198Sbostic *value += 5; 30530198Sbostic if (!cango) 30630198Sbostic *value /= ++badcount; 30730198Sbostic if (op->mileage == 0) 30830198Sbostic *value += 5; 30930198Sbostic if ((card == C_LIMIT && 31030198Sbostic op->speed == C_LIMIT) || 31130198Sbostic !op->can_go) 31230198Sbostic *value -= 5; 31330198Sbostic if (cango && pp->safety[S_RIGHT_WAY] != 31430198Sbostic S_UNKNOWN) 31530198Sbostic *value += 5; 31630198Sbostic } 31730198Sbostic break; 31830198Sbostic case C_GAS_SAFE: case C_DRIVE_SAFE: 31930198Sbostic case C_SPARE_SAFE: case C_RIGHT_WAY: 32030198Sbostic *value = cango ? 0 : 101; 32130198Sbostic break; 32230198Sbostic case C_INIT: 32330198Sbostic *value = 0; 32430198Sbostic break; 32530198Sbostic } 32630198Sbostic } 32730198Sbostic else 32830198Sbostic *value = cango ? 0 : 101; 32930198Sbostic if (card != C_INIT) { 33030198Sbostic if (*value >= curmax) { 33130198Sbostic nummax = i; 33230198Sbostic curmax = *value; 33330198Sbostic } 33430198Sbostic if (*value <= curmin) { 33530198Sbostic nummin = i; 33630198Sbostic curmin = *value; 33730198Sbostic } 33830198Sbostic } 33933170Sbostic #ifdef DEBUG 34030198Sbostic if (Debug) 34130198Sbostic mvprintw(i + 6, 2, "%3d %-14s", *value, 34230198Sbostic C_name[pp->hand[i]]); 34333170Sbostic #endif 34430198Sbostic value++; 34530198Sbostic } 34630198Sbostic if (!pp->can_go && !isrepair(pp->battle)) 34730198Sbostic Numneed[opposite(pp->battle)]++; 34830198Sbostic if (cango) { 34930198Sbostic play_it: 35030198Sbostic mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n"); 35133170Sbostic #ifdef DEBUG 35230198Sbostic if (Debug) 35330198Sbostic getmove(); 35430198Sbostic if (!Debug || Movetype == M_DRAW) { 35533170Sbostic #else 35633170Sbostic if (Movetype == M_DRAW) { 35733170Sbostic #endif 35830198Sbostic Movetype = M_PLAY; 35930198Sbostic Card_no = nummax; 36030198Sbostic } 36130198Sbostic } 36230198Sbostic else { 36330198Sbostic if (issafety(pp->hand[nummin])) { /* NEVER discard a safety */ 36430198Sbostic nummax = nummin; 36530198Sbostic goto play_it; 36630198Sbostic } 36730198Sbostic mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n"); 36833170Sbostic #ifdef DEBUG 36930198Sbostic if (Debug) 37030198Sbostic getmove(); 37130198Sbostic if (!Debug || Movetype == M_DRAW) { 37233170Sbostic #else 37333170Sbostic if (Movetype == M_DRAW) { 37433170Sbostic #endif 37530198Sbostic Movetype = M_DISCARD; 37630198Sbostic Card_no = nummin; 37730198Sbostic } 37830198Sbostic } 37930198Sbostic mvprintw(MOVE_Y + 2, MOVE_X, "%16s", C_name[pp->hand[Card_no]]); 38030198Sbostic } 38130198Sbostic 38230198Sbostic onecard(pp) 38330198Sbostic register PLAY *pp; 38430198Sbostic { 38530198Sbostic register CARD bat, spd, card; 38630198Sbostic 38730198Sbostic bat = pp->battle; 38830198Sbostic spd = pp->speed; 38930198Sbostic card = -1; 39030198Sbostic if (pp->can_go || ((isrepair(bat) || bat == C_STOP || spd == C_LIMIT) && 39130198Sbostic Numseen[S_RIGHT_WAY] != 0) || 392*52872Storek bat >= 0 && Numseen[safety(bat)] != 0) 39330198Sbostic switch (End - pp->mileage) { 39430198Sbostic case 200: 39530198Sbostic if (pp->nummiles[C_200] == 2) 39630198Sbostic return FALSE; 39730198Sbostic card = C_200; 39830198Sbostic /* FALLTHROUGH */ 39930198Sbostic case 100: 40030198Sbostic case 75: 40130198Sbostic if (card == -1) 40230198Sbostic card = (End - pp->mileage == 75 ? C_75 : C_100); 40330198Sbostic if (spd == C_LIMIT) 40430198Sbostic return Numseen[S_RIGHT_WAY] == 0; 40530198Sbostic case 50: 40630198Sbostic case 25: 40730198Sbostic if (card == -1) 40830198Sbostic card = (End - pp->mileage == 25 ? C_25 : C_50); 40930198Sbostic return Numseen[card] != Numcards[card]; 41030198Sbostic } 41130198Sbostic return FALSE; 41230198Sbostic } 41330198Sbostic 41430198Sbostic canplay(pp, op, card) 41530198Sbostic register PLAY *pp, *op; 41630198Sbostic register CARD card; 41730198Sbostic { 41830198Sbostic switch (card) { 41930198Sbostic case C_200: 42030198Sbostic if (pp->nummiles[C_200] == 2) 42130198Sbostic break; 42230198Sbostic /* FALLTHROUGH */ 42330198Sbostic case C_75: case C_100: 42430198Sbostic if (pp->speed == C_LIMIT) 42530198Sbostic break; 42630198Sbostic /* FALLTHROUGH */ 42730198Sbostic case C_50: 42830198Sbostic if (pp->mileage + Value[card] > End) 42930198Sbostic break; 43030198Sbostic /* FALLTHROUGH */ 43130198Sbostic case C_25: 43230198Sbostic if (pp->can_go) 43330198Sbostic return TRUE; 43430198Sbostic break; 43530198Sbostic case C_EMPTY: case C_FLAT: case C_CRASH: 43630198Sbostic case C_STOP: 43730198Sbostic if (op->can_go && op->safety[safety(card) - S_CONV] != S_PLAYED) 43830198Sbostic return TRUE; 43930198Sbostic break; 44030198Sbostic case C_LIMIT: 44130198Sbostic if (op->speed != C_LIMIT && 44230198Sbostic op->safety[S_RIGHT_WAY] != S_PLAYED && 44330198Sbostic op->mileage + 50 < End) 44430198Sbostic return TRUE; 44530198Sbostic break; 44630198Sbostic case C_GAS: case C_SPARE: case C_REPAIRS: 44730198Sbostic if (pp->battle == opposite(card)) 44830198Sbostic return TRUE; 44930198Sbostic break; 45030198Sbostic case C_GO: 45130198Sbostic if (!pp->can_go && 45230198Sbostic (isrepair(pp->battle) || pp->battle == C_STOP)) 45330198Sbostic return TRUE; 45430198Sbostic break; 45530198Sbostic case C_END_LIMIT: 45630198Sbostic if (pp->speed == C_LIMIT) 45730198Sbostic return TRUE; 45830198Sbostic } 45930198Sbostic return FALSE; 46030198Sbostic } 461