Logo Search packages:      
Sourcecode: vgacardgames version File versions  Download package

ohhell.c

/*
 * Oh Hell!
 *
 * Copyright (C) Evan Harris, 1991, 1993, 1994
 *
 * Permission is granted to freely redistribute and modify this code,
 * providing the author(s) get credit for having written it.
 */

#include <stdlib.h>
#ifdef PRINTPROGRESS
#include <stdio.h>
#endif
#include "ohhell.h"

unsigned char hand[NUMPLAYERS][NUMHANDS];
unsigned char bid[NUMPLAYERS];
unsigned char wins[NUMPLAYERS];
unsigned char score[NUMPLAYERS];
unsigned char played[NUMPLAYERS];
unsigned char trumps;
unsigned char led;


void
main(int argc, char **argv)
{
    unsigned char deal = 1;
    unsigned char first = 0;

    InitDisplay(argc, argv);
    InitRandom(NEW);
    InitGame();

    for (;;) {
      switch (PlayGame(deal, first)) {
        case NEWGAME:
          InitGame();
          deal = 1;
          first = (first + 1) % NUMPLAYERS;
          break;
        case NEXTGAME:
          deal++;
          first = (first + 1) % NUMPLAYERS;
          break;
        case QUIT:
          EndDisplay();
          exit(0);
          break;
      }
    }

}


void
InitGame()
{
    unsigned char i;
  
    for (i = 0; i < NUMPLAYERS; i++)
      score[i] = 0;
    ShowScores(score);
  
    return;
}


short
PlayGame(unsigned char deal, unsigned char first)
{
    unsigned char i, j;
    short b, best;
    short key;
    short cmd;
    unsigned char lead = first;

    if (deal > NUMHANDS) {
      do {
          cmd = GetCmd();
      }
      while (cmd != NEWGAME && cmd != QUIT);
      return cmd;
    }

    trumps = Deal(deal);

    for (i = 0; i < NUMPLAYERS; i++) {
      wins[i] = 0;
    }
    ShowWins(wins);

    RemoveBids();
    for (i = first; i < first + NUMPLAYERS; i++) {
      b = GetBid(i % NUMPLAYERS, deal, first);
      if (b == NEWGAME || b == QUIT) return b;
      bid[i % NUMPLAYERS] = b;
      ShowBid(bid[i % NUMPLAYERS], i % NUMPLAYERS);
    }

    for (i = 0; i < deal; i++) {
      for (j = 0; j < NUMPLAYERS; j++) {
          played[j] = NOCARD;
      }
      led = NOCARD;
      for (j = lead; j < lead + NUMPLAYERS; j++) {
          b = GetPlay(j % NUMPLAYERS, deal, lead);
          if (b == NEWGAME || b == QUIT) return b;

          ShowPlay(b, j % NUMPLAYERS);
          if (j % NUMPLAYERS == 0)
            ShowHand(hand[0], deal);
          played[j % NUMPLAYERS] = b;
          if (led == NOCARD)
            led = b;
      }
      best = -1;
      for (j = lead; j < lead + NUMPLAYERS; j++) {
          if (best == -1 || 
            (SUIT(played[j % NUMPLAYERS]) == SUIT(played[best]) && 
             (TYPE(played[j % NUMPLAYERS]) + 12) % 13 > 
             (TYPE(played[best]) + 12) % 13) ||
            (SUIT(played[j % NUMPLAYERS]) == trumps && 
             SUIT(played[best]) != trumps)) {
            best = j % NUMPLAYERS;
          }
      }
      wins[best]++;
      lead = best;
      ShowWins(wins);
      key = WaitForKey();
      RemovePlays();
      if (key != CONTINUE)
          return key;
    }
  
    for (i = 0; i < NUMPLAYERS; i++) {
      if (wins[i] == bid[i])
          score[i] += 10 + bid[i];
    }
    ShowScores(score);

    return NEXTGAME;
}


unsigned char
Deal(unsigned char deal)
{
    unsigned char cards[NUMCARDS];
    unsigned char i, j, k;
    short r;
  
    for (i = 0; i < NUMCARDS; i++) {
      cards[i] = 0;
    }
    for (i = 0; i < deal; i++) {
      for (j = 0; j < NUMPLAYERS; j++) {
          r = Random(NUMCARDS - (i * NUMPLAYERS + j));
          for (k = 0; k < NUMCARDS && r >= 0; k++) {
            if (cards[k] == 0)
                r--;
          }
          r = k - 1;
          cards[r] = 1;
      
          hand[j][i] = r;
      }
    }
  
    if (deal * NUMPLAYERS < NUMCARDS) {
      r = Random(NUMCARDS - deal * NUMPLAYERS);
      for (k = 0; k < NUMCARDS && r >= 0; k++) {
          if (cards[k] == 0)
            r--;
      }
      trumps = k - 1;

      ShowTrumps(trumps);
      trumps = SUIT(trumps);
    } 
    else {
      RemoveTrumps();
      trumps = NOSUIT;
    }

    qsort(hand[0], deal, sizeof(unsigned char), (__compar_fn_t)&Cmp);
    ShowHand(hand[0], deal);

    return trumps;
}


short
GetBid(unsigned char player, unsigned char deal, unsigned char first)
{
    short bid = 0;
    unsigned char i, numtrumps = 0;

    if (player == 0)
      return GetPlayerBid(deal);

    for (i = 0; i < deal; i++) {
      if (TYPE(hand[player][i]) == ACE || TYPE(hand[player][i]) == KING ||
          TYPE(hand[player][i]) == QUEEN)
          bid++;
      else if (SUIT(hand[player][i]) == trumps)
          numtrumps++;
    }

    if (deal < 4 && player == first)
      bid++;
    if (numtrumps > deal / 4)
      bid += numtrumps - deal / 4;
    if (bid > deal)
      bid = deal;

    return bid;
}


short
GetPlay(unsigned char player, unsigned char deal, unsigned char first)
{
#ifdef PRINTPROGRESS
    static char suits[] = { 's', 'c', 'h', 'd' };
    static char types[] = { 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };
#endif
    short cmd = NOCARD, ret;
    unsigned char i;
    unsigned char best = NOCARD;
    unsigned char wanttowin;
    unsigned char winning;
    short smallestwinner, biggestwinner, smallestloser, biggestloser;
    unsigned char legal[NUMCARDS / NUMPLAYERS];
    unsigned char numlegal;
    unsigned char under, over, equal;

    if (player == 0) {
      while (cmd == NOCARD) {
#if 0
          FlushIn();
#endif
          cmd = GetCmd();
          if (cmd < 0)
            return cmd;
          else if (led != NOCARD && 
                 SUIT(hand[player][cmd]) != SUIT(led)) {
            for (i = 0; i < deal; i++)
                if (hand[player][i] != NOCARD &&
                  SUIT(hand[player][i]) == SUIT(led))
                  cmd = NOCARD;
          }
      }
      ret = hand[player][cmd];
      hand[player][cmd] = NOCARD;
      return ret;
    }

#ifdef PRINTPROGRESS
    if (led == NOCARD) fprintf(stderr, "\n");
    fprintf(stderr, "Player %d : ", player);
    for (i = 0; i < deal; i++)
      if (hand[player][i] != NOCARD)
          fprintf(stderr, "%c%c ", types[TYPE(hand[player][i])],
                suits[SUIT(hand[player][i])]);
#endif

    if (led != NOCARD) {
      /*
       * Find which card that has been played is winning.
       */
      winning = led;
      for (i = (first + 1) % NUMPLAYERS;
           i != player;
           i = (i + 1) % NUMPLAYERS) {
          if ((SUIT(played[i]) == SUIT(winning)
             && TYPECMP(played[i], winning) > 0) || 
            (SUIT(played[i]) == trumps && SUIT(winning) != trumps))
            winning = played[i];
      }

      /*
       * Find all the legal cards.  First a pass looking for suit cards.
       */
      numlegal = 0;
      for (i = 0; i < deal; i++) {
          if (hand[player][i] != NOCARD
            && SUIT(hand[player][i]) == SUIT(led)) {
            legal[numlegal] = i;
            numlegal++;
          }
      }

#ifdef PRINTPROGRESS
      fprintf(stderr, " legal : %d ", numlegal);
#endif

      smallestloser = biggestloser = smallestwinner = biggestwinner = -1;
      if (numlegal > 0) {
          /*
           * Look amongst suit cards for all winners and losers.
           */
          for (i = 0; i < numlegal; i++) {
            if ((SUIT(led) == trumps || SUIT(winning) != trumps) && 
                TYPECMP(winning, hand[player][legal[i]]) < 0) {
                if (smallestwinner == -1)
                  smallestwinner = biggestwinner = legal[i];
                else if (TYPECMP(hand[player][smallestwinner],
                             hand[player][legal[i]]) > 0)
                  smallestwinner = legal[i];
                else if (TYPECMP(hand[player][biggestwinner],
                             hand[player][legal[i]]) < 0)
                  biggestwinner = legal[i];
            } else {
                if (smallestloser == -1)
                  smallestloser = biggestloser = legal[i];
                else if (TYPECMP(hand[player][smallestloser],
                             hand[player][legal[i]]) > 0)
                  smallestloser = legal[i];
                else if (TYPECMP(hand[player][biggestloser],
                             hand[player][legal[i]]) < 0)
                  biggestloser = legal[i];
            }
          }
      } else {
          /*
           * Look amongst all cards for winners (trumps) and losers (others).
           */
          for (i = 0; i < deal; i++) {
            if (hand[player][i] != NOCARD) {
                if (SUIT(hand[player][i]) == trumps &&
                  (SUIT(winning) != trumps
                   || TYPECMP(winning, hand[player][i]) < 0)) {
                  if (smallestwinner == -1)
                      smallestwinner = biggestwinner = i;
                  else if (TYPECMP(hand[player][smallestwinner],
                               hand[player][i]) > 0)
                      smallestwinner = i;
                  else if (TYPECMP(hand[player][biggestwinner],
                               hand[player][i]) < 0)
                      biggestwinner = i;
                } 
                else {
                  if (smallestloser == -1)
                      smallestloser = biggestloser = i;
                  else if ((SUIT(hand[player][smallestloser]) == trumps
                          && SUIT(hand[player][i]) != trumps)
                         || TYPECMP(hand[player][smallestloser],
                                  hand[player][i]) > 0)
                      smallestloser = i;
                  else if ((SUIT(hand[player][smallestloser]) != trumps
                          && SUIT(hand[player][i]) == trumps)
                         || TYPECMP(hand[player][biggestloser],
                                  hand[player][i]) < 0)
                      biggestloser = i;
                }
            }
          }
      }
    }

    under = over = equal = 0;
    for (i = 0; i < NUMPLAYERS; i++) {
      if (i != player) {
          if (wins[player] < bid[player])
            under++;
          else if (wins[player] > bid[player])
            over++;
          else
            equal++;
      }
    }

    if (wins[player] < bid[player])
      wanttowin = TRUE;
    else
      wanttowin = FALSE;

    if (led == NOCARD) {
      for (i = 0; i < deal; i++) {
          if (hand[player][i] != NOCARD) {
            if (best == NOCARD ||
                (wanttowin &&
                 TYPECMP(hand[player][best], hand[player][i]) < 0) ||
                (!wanttowin &&
                 TYPECMP(hand[player][best], hand[player][i]) > 0))
                best = i;
          }
      }
    }
    else {
#ifdef PRINTPROGRESS
      if (smallestloser != -1)
          fprintf(stderr, " sl : %c%c",
                types[TYPE(hand[player][smallestloser])],
                suits[SUIT(hand[player][smallestloser])]);
      if (biggestloser != -1)
          fprintf(stderr, " bl : %c%c",
                types[TYPE(hand[player][biggestloser])],
                suits[SUIT(hand[player][biggestloser])]);
      if (smallestwinner != -1)
          fprintf(stderr, " sw : %c%c",
                types[TYPE(hand[player][smallestwinner])],
                suits[SUIT(hand[player][smallestwinner])]);
      if (biggestwinner != -1)
          fprintf(stderr, " bw : %c%c ",
                types[TYPE(hand[player][biggestwinner])],
                suits[SUIT(hand[player][biggestwinner])]);
#endif

      if (wanttowin) {
          if (smallestwinner != -1) {
            if (player == (first - 1 + NUMPLAYERS) % NUMPLAYERS)
                best = smallestwinner;
            else
                best = biggestwinner;
          }
          else
            best = smallestloser;
      }
      else {
          if (biggestloser != -1)
            best = biggestloser;
          else if (equal >= under)
            best = smallestwinner;
          else
            best = biggestwinner;
      }
    }

#ifdef PRINTPROGRESS
    fprintf(stderr, " playing : %c%c\n", types[TYPE(hand[player][best])],
          suits[SUIT(hand[player][best])]);
#endif

    ret = hand[player][best];
    hand[player][best] = NOCARD;

    return ret;
}


int Cmp(unsigned char *a, unsigned char *b)
{
    static unsigned char remap[4] = { 0, 2, 1, 3 };
    unsigned char arank = CARD(remap[SUIT(*a)], (TYPE(*a) + 12) % 13);
    unsigned char brank = CARD(remap[SUIT(*b)], (TYPE(*b) + 12) % 13);

    if (arank < brank) return 1;
    if (arank > brank) return -1;
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index