|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 8310 (0x2076) Types: TextFile Names: »move.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/X/Xmille/move.c«
#include "mille.h" /* * @(#)move.c 1.3 (Berkeley) 7/2/83 */ #ifdef CTRL #undef CTRL #endif #define CTRL(c) (c - 'A' + 1) char *Movenames[] = { "M_DISCARD", "M_DRAW", "M_PLAY", "M_ORDER" }; char *playcard (), *sprint (); domove() { reg PLAY *pp; reg int i, j; reg bool goodplay; char *foo; pp = &Player[Play]; if (Play == PLAYER) getmove(); else calcmove(); Next = FALSE; goodplay = TRUE; switch (Movetype) { case M_DISCARD: trydiscard: ; if (haspicked(pp)) { if (pp->hand[Card_no] == C_INIT) if (Card_no == 6) Finished = TRUE; else error("no card there"); else { Discard = pp->hand[Card_no]; pp->hand[Card_no] = C_INIT; #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_DISC, Discard); #endif Next = TRUE; if (Play == PLAYER) account(Discard); } } else error("must pick first"); break; case M_REASONABLE: case M_PLAY: foo = playcard(pp); if (foo) { if (Movetype == M_REASONABLE) goto trydiscard; error (foo); goodplay = 0; } else goodplay = 1; break; case M_DRAW: Card_no = 0; if (Topcard <= Deck) error("no more cards"); else if (haspicked(pp)) error("already picked"); else { pp->hand[0] = *--Topcard; #ifdef ANIMATE animate_move (Play, ANIMATE_DECK, pp->hand[0], ANIMATE_HAND, 0); #endif if (Debug) fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]); acc: if (Play == COMP) { account(*Topcard); if (issafety(*Topcard)) pp->safety[*Topcard-S_CONV] = S_IN_HAND; } if (pp->hand[1] == C_INIT && Topcard > Deck) { Card_no = 1; pp->hand[1] = *--Topcard; if (Debug) fprintf(outf, "DOMOVE: Draw %s\n", C_name[*Topcard]); goto acc; } pp->new_battle = FALSE; pp->new_speed = FALSE; } break; case M_ORDER: break; } /* * move blank card to top by one of two methods. If the * computer's hand was sorted, the randomness for picking * between equally valued cards would be lost */ if (Order && Movetype != M_DRAW && goodplay && pp == &Player[PLAYER]) sort(pp->hand); else for (i = 1; i < HAND_SZ; i++) if (pp->hand[i] == C_INIT) { for (j = 0; pp->hand[j] == C_INIT; j++) if (j >= HAND_SZ) { j = 0; break; } pp->hand[i] = pp->hand[j]; pp->hand[j] = C_INIT; } if (Topcard <= Deck) check_go(); if (Next) nextplay(); } /* * Check and see if either side can go. If they cannot, * the game is over */ check_go() { reg CARD card; reg PLAY *pp, *op; reg int i; for (pp = Player; pp < &Player[2]; pp++) { op = (pp == &Player[COMP] ? &Player[PLAYER] : &Player[COMP]); for (i = 0; i < HAND_SZ; i++) { card = pp->hand[i]; if (issafety(card) || canplay(pp, op, card)) { if (Debug) { fprintf(outf, "CHECK_GO: can play %s (%d), ", C_name[card], card); fprintf(outf, "issafety(card) = %d, ", issafety(card)); fprintf(outf, "canplay(pp, op, card) = %d\n", canplay(pp, op, card)); } return; } else if (Debug) fprintf(outf, "CHECK_GO: cannot play %s\n", C_name[card]); } } Finished = TRUE; } char * playcard(pp) reg PLAY *pp; { reg int v; reg CARD card; /* * check and see if player has picked */ switch (pp->hand[Card_no]) { default: if (!haspicked(pp)) mustpick: return ("must pick first"); case C_GAS_SAFE: case C_SPARE_SAFE: case C_DRIVE_SAFE: case C_RIGHT_WAY: break; } card = pp->hand[Card_no]; if (Debug) fprintf(outf, "PLAYCARD: Card = %s\n", C_name[card]); Next = FALSE; switch (card) { case C_200: if (pp->nummiles[C_200] == 2) return ("only two 200's per hand"); case C_100: case C_75: if (pp->speed == C_LIMIT) return ("limit of 50"); case C_50: if (pp->mileage + Value[card] > End) return sprint ("puts you over %d", End); case C_25: if (!pp->can_go) return ("cannot move now"); #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_MILES, card); #endif pp->nummiles[card]++; v = Value[card]; pp->total += v; pp->hand_tot += v; if ((pp->mileage += v) == End) check_ext(FALSE); break; case C_GAS: case C_SPARE: case C_REPAIRS: if (pp->battle != opposite(card)) return sprint ("can't play \"%s\"", C_name[card]); #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_BATTLE, card); #endif pp->battle = card; if (pp->safety[S_RIGHT_WAY] == S_PLAYED) pp->can_go = TRUE; break; case C_GO: if (pp->battle != C_INIT && pp->battle != C_STOP && !isrepair(pp->battle)) return sprint ("cannot play \"Go\" on a \"%s\"", C_name[pp->battle]); #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_BATTLE, card); #endif pp->battle = C_GO; pp->can_go = TRUE; break; case C_END_LIMIT: if (pp->speed != C_LIMIT) return ("not limited"); #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_SPEED, card); #endif pp->speed = C_END_LIMIT; break; case C_EMPTY: case C_FLAT: case C_CRASH: case C_STOP: pp = &Player[other(Play)]; if (!pp->can_go) return ("opponent cannot go"); else if (pp->safety[safety(card) - S_CONV] == S_PLAYED) protected: return ("opponent is protected"); #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_OBATTLE, card); #endif pp->battle = card; pp->new_battle = TRUE; pp->can_go = FALSE; pp = &Player[Play]; break; case C_LIMIT: pp = &Player[other(Play)]; if (pp->speed == C_LIMIT) return ("opponent has limit"); if (pp->safety[S_RIGHT_WAY] == S_PLAYED) goto protected; #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_OSPEED, card); #endif pp->speed = C_LIMIT; pp->new_speed = TRUE; pp = &Player[Play]; break; case C_GAS_SAFE: case C_SPARE_SAFE: case C_DRIVE_SAFE: case C_RIGHT_WAY: if (pp->battle == opposite(card) || (card == C_RIGHT_WAY && pp->speed == C_LIMIT)) { if (!(card == C_RIGHT_WAY && !isrepair(pp->battle))) { pp->battle = C_GO; pp->can_go = TRUE; } if (card == C_RIGHT_WAY && pp->speed == C_LIMIT) pp->speed = C_INIT; if (pp->new_battle || (pp->new_speed && card == C_RIGHT_WAY)) { pp->coups[card - S_CONV] = TRUE; pp->total += SC_COUP; pp->hand_tot += SC_COUP; pp->coupscore += SC_COUP; } } /* * if not coup, must pick first */ else if (pp->hand[0] == C_INIT && Topcard > Deck) goto mustpick; #ifdef ANIMATE animate_move (Play, ANIMATE_HAND, Card_no, ANIMATE_SAFETY, card); #endif pp->safety[card - S_CONV] = S_PLAYED; pp->total += SC_SAFETY; pp->hand_tot += SC_SAFETY; if ((pp->safescore += SC_SAFETY) == NUM_SAFE * SC_SAFETY) { pp->total += SC_ALL_SAFE; pp->hand_tot += SC_ALL_SAFE; } if (card == C_RIGHT_WAY) { if (pp->speed == C_LIMIT) pp->speed = C_INIT; if (pp->battle == C_STOP || pp->battle == C_INIT) { pp->can_go = TRUE; pp->battle = C_INIT; } if (!pp->can_go && isrepair(pp->battle)) pp->can_go = TRUE; } Next = -1; break; case C_INIT: Next = -1; return ("no card there"); break; } if (pp == &Player[PLAYER]) account(card); pp->hand[Card_no] = C_INIT; Next = (Next == -1 ? FALSE : TRUE); return 0; } char * sprint (string, arg) { static char buf[512]; sprintf (buf, string, arg); return buf; } /* * return whether or not the player has picked */ haspicked(pp) reg PLAY *pp; { reg int card; if (Topcard <= Deck) return TRUE; switch (pp->hand[Card_no]) { case C_GAS_SAFE: case C_SPARE_SAFE: case C_DRIVE_SAFE: case C_RIGHT_WAY: card = 1; break; default: card = 0; break; } return (pp->hand[card] != C_INIT); } account(card) reg CARD card; { reg CARD oppos; if (card == C_INIT) return; ++Numseen[card]; if (Play == COMP) switch (card) { case C_GAS_SAFE: case C_SPARE_SAFE: case C_DRIVE_SAFE: oppos = opposite(card); Numgos += Numcards[oppos] - Numseen[oppos]; break; case C_CRASH: case C_FLAT: case C_EMPTY: case C_STOP: Numgos++; break; } } sort(hand) reg CARD *hand; { reg CARD *cp, *tp; reg int j; reg CARD temp; cp = hand; hand += HAND_SZ; for ( ; cp < &hand[-1]; cp++) for (tp = cp + 1; tp < hand; tp++) if (*cp > *tp) { temp = *cp; *cp = *tp; *tp = temp; } }