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