#include <perms.h>

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  %BEGIN

int main(int argc, char **argv) { /*%begin*/
  _imp_initialise(argc, argv);

  //     2
  //     3
  //     4  %BYTEINTEGERARRAY DEAL(1:52)

  unsigned char DEAL[52];
  struct _imp_dv DEAL_dv = {DEAL, sizeof(unsigned char) /*, dims, <bounds> */};

  //     5  %BYTEINTEGERARRAY HAND(0:3,2:14)

  unsigned char HAND[4][13];
  struct _imp_dv HAND_dv = {HAND, sizeof(unsigned char) /*, dims, <bounds> */};

  //     6  %OWNBYTEINTEGERARRAY S(0:3)='S','H','D','C'

  static unsigned char S[4] = {83, 72, 68, 67};
  struct _imp_dv S_dv = {S, sizeof(unsigned char) /*, dims, <bounds> */};

  //     7  %INTEGER POINTS,BALANCE,LIMIT,CUT

  int POINTS;
  int BALANCE;
  int LIMIT;
  int CUT;

  //     8  %INTEGERARRAY DIST,PTS(0:3)

  int DIST[4];
  struct _imp_dv DIST_dv = {DIST, sizeof(int) /*, dims, <bounds> */};

  int PTS[4];
  struct _imp_dv PTS_dv = {PTS, sizeof(int) /*, dims, <bounds> */};

  //     9  %OWNINTEGER HANDCOUNT=0

  static int HANDCOUNT = 0;

  //    10
  //    11  %ROUTINE INITIALISE; ! INITIALISES PACK

  void INITIALISE(void) {
    //    12     %INTEGER I,J,K

    int I;
    int J;
    int K;

    //    13     K=-1

    K = -1;

    //    14     %CYCLE I=0,16,48; ! SUIT

    // %for I = 0, 16, 48 %cycle
    {
      I = -16;
    L_0001:
      if (I == 48) goto L_0002;
      I += 16;

      //    15         %CYCLE J=2,1,14; ! VALUE

      // %for J = 2, 1, 14 %cycle
      {
        J = 1;
      L_0004:
        if (J == 14) goto L_0005;
        J += 1;

        //    16             DEAL(K+J)=I+J

        DEAL[K + J - 1] = I + J;

        //    17         %REPEAT; K=K+13; %REPEAT

        goto L_0004;
      }

    L_0005:;
      K = K + 13;
      goto L_0001;
    }

  L_0002:;

  //    18     %END; ! OF INITIALISE

    return;
  } /* end of INITIALISE */

  //    19
  //    20  %ROUTINE SHUFFLE; ! SHUFFLES AND CUTS PACK

  void SHUFFLE(void) {
    //    21     %BYTEINTEGERARRAY A(1:52)

    unsigned char A[52];
    struct _imp_dv A_dv = {A, sizeof(unsigned char) /*, dims, <bounds> */};

    //    22     %INTEGER I,J

    int I;
    int J;

    //    23     %CYCLE I=1,1,26

    // %for I = 1, 1, 26 %cycle
    {
      I = 0;
    L_0007:
      if (I == 26) goto L_0008;
      I += 1;

      //    24        A(2*I-1)=DEAL(I); A(2*I)=DEAL(53-I)

      A[2 * I - 1 - 1] = DEAL[I - 1];
      A[2 * I - 1] = DEAL[53 - I - 1];

      //    25        %REPEAT

      goto L_0007;
    }

  L_0008:;

  //    26     CUT=CUT+11

    CUT = CUT + 11;

    //    27     %IF CUT>=52 %THEN CUT=CUT-52

    if (CUT < 52) goto L_0009;
    CUT = CUT - 52;
  L_0009:;

  //    28     %IF CUT=0 %THEN CUT=1

    if (CUT != 0) goto L_000A;
    CUT = 1;
  L_000A:;

  //    29     %CYCLE I=1,1,CUT

    // %for I = 1, 1, CUT %cycle
    {
      int _final = CUT;
      if (invalid_for_loop(1, 1, _final)) _imp_signal(5, 1, 0, "Illegal cycle I = 1, 1, CUT");
      I = 0;
    L_000B:
      if (I == _final) goto L_000C;
      I += 1;

      //    30        DEAL(52-CUT+I)=A(I); %REPEAT

      DEAL[52 - CUT + I - 1] = A[I - 1];
      goto L_000B;
    }

  L_000C:;

  //    31     %CYCLE I=CUT+1,1,52

    // %for I = CUT + 1, 1, 52 %cycle
    {
      int _initial = CUT + 1;
      if (invalid_for_loop(_initial, 1, 52)) _imp_signal(5, 1, 0, "Illegal cycle I = CUT + 1, 1, 52");
      I = _initial - (1);
    L_000D:
      if (I == 52) goto L_000E;
      I += 1;

      //    32        DEAL(I-CUT)=A(I); %REPEAT

      DEAL[I - CUT - 1] = A[I - 1];
      goto L_000D;
    }

  L_000E:;

  //    33     %END;

    return;
  } /* end of SHUFFLE */

  // ?J unused
  //    34          ; ! OF SHUFFLE
  //    34
  //    35  %ROUTINE DEALPACK

  void DEALPACK(void) {
    //    36     %OWNBYTEINTEGERARRAY T(11:14)='J','Q','K','A'

    static unsigned char T[4] = {74, 81, 75, 65};
    struct _imp_dv T_dv = {T, sizeof(unsigned char) /*, dims, <bounds> */};

    //    37     %INTEGER I,J,K,M

    int I;
    int J;
    int K;
    int M;

    //    38     POINTS=0;BALANCE=0

    POINTS = 0;
    BALANCE = 0;

    //    39     %IF HANDCOUNT&7=0 %THENSTART

    if (HANDCOUNT & 7 != 0) goto L_000F;

      //    40        NEWPAGE; print string("BRIDGEHANDS")

    _imp_NEWPAGE();
    _imp_PRINTSTRING(_imp_str_literal("BRIDGEHANDS"));

    //    41        NEWLINES(3); %FINISH

    _imp_NEWLINES(3);
  L_000F:;

  //    42     %CYCLE I=0,1,3

    // %for I = 0, 1, 3 %cycle
    {
      I = -1;
    L_0010:
      if (I == 3) goto L_0011;
      I += 1;

      //    43        %CYCLE J=2,1,14

      // %for J = 2, 1, 14 %cycle
      {
        J = 1;
      L_0012:
        if (J == 14) goto L_0013;
        J += 1;

        //    44           HAND(I,J)=0; %REPEAT; %REPEAT

        HAND[I][J - 2] = 0;
        goto L_0012;
      }

    L_0013:;
      goto L_0010;
    }

  L_0011:;

  //    45     %CYCLE I=1,4,49

    // %for I = 1, 4, 49 %cycle
    {
      I = -3;
    L_0014:
      if (I == 49) goto L_0015;
      I += 4;

      //    46        HAND(DEAL(I)>>4,DEAL(I)&15)=1

      HAND[(unsigned int)DEAL[I - 1] >> 4][(DEAL[I - 1] & 15) - 2] = 1;

      //    47        %REPEAT

      goto L_0014;
    }

  L_0015:;

  //    48     %CYCLE I=0,1,3

    // %for I = 0, 1, 3 %cycle
    {
      I = -1;
    L_0016:
      if (I == 3) goto L_0017;
      I += 1;

      //    49        K=0; PRINTSYMBOL(S(I)); SPACES(3)

      K = 0;
      _imp_PRINTSYMBOL(S[I]);
      _imp_SPACES(3);

      //    50        M=0; ! COUNTS POINTS

      M = 0;

      //    51        %CYCLE J=14,-1,11

      // %for J = 14,  -1, 11 %cycle
      {
        J = 15;
      L_0018:
        if (J == 11) goto L_0019;
        J -= 1;

        //    52           ->L1 %IF HAND(I,J)=0

        if (HAND[I][J - 2] != 0) goto L_001A;
        goto U_1000;
      L_001A:;

      //    53           SPACE;PRINTSYMBOL(T(J));K=K+1;M=M+J-10

        _imp_SPACE();
        _imp_PRINTSYMBOL(T[J - 11]);
        K = K + 1;
        M = M + J - 10;

        //    54    L1:    %REPEAT

      U_1000:;
        goto L_0018;
      }

    L_0019:;

    //    55        %IF HAND(I,10)#0 %THENSTART

      if (HAND[I][8] == 0) goto L_001B;

        //    56           WRITE(10,2); K=K+1; %FINISH

      _imp_WRITE(10, 2);
      K = K + 1;
    L_001B:;

    //    57        %CYCLE J=9,-1,2

      // %for J = 9,  -1, 2 %cycle
      {
        J = 10;
      L_001C:
        if (J == 2) goto L_001D;
        J -= 1;

        //    58           ->L2 %IF HAND(I,J)=0

        if (HAND[I][J - 2] != 0) goto L_001E;
        goto U_1001;
      L_001E:;

      //    59           K=K+1; WRITE(J,1)

        K = K + 1;
        _imp_WRITE(J, 1);

        //    60    L2:     %REPEAT

      U_1001:;
        goto L_001C;
      }

    L_001D:;

    //    61        %IF K=0 %THEN print string(" --")

      if (K != 0) goto L_001F;
      _imp_PRINTSTRING(_imp_str_literal(" --"));
    L_001F:;

    //    62        %IF 1<=M<=3 %AND K=1 %THEN M=M-1

      {
        // Double-sided test on M (Part I)
        int tmp;
        if (1 > (tmp = M)) goto L_0020;
        // Double-sided test on M (Part II)
        if (tmp > 3) goto L_0020;
      }
      if (K != 1) goto L_0020;
      M = M - 1;
    L_0020:;

    //    63        PTS(I)=M; POINTS=POINTS+M; DIST(I)=K

      PTS[I] = M;
      POINTS = POINTS + M;
      DIST[I] = K;

      //    64        %IF K>5 %THEN BALANCE=BALANCE+K-5

      if (K <= 5) goto L_0021;
      BALANCE = BALANCE + K - 5;
    L_0021:;

    //    65                 %IF K<2 %THEN BALANCE=BALANCE+2{-???}

      if (K >= 2) goto L_0022;
      BALANCE = BALANCE + 2;
    L_0022:;

    //    66              NEWLINE; %REPEAT

      _imp_NEWLINE();
      goto L_0016;
    }

  L_0017:;

  //    67           HANDCOUNT=HANDCOUNT+1

    HANDCOUNT = HANDCOUNT + 1;

    //    68           %END; ! OF DEAL

    return;
  } /* end of DEALPACK */

  //    69
  //    70        INITIALISE; READ(CUT); READ(LIMIT)

  INITIALISE();
  _imp_READ(/*?*/ &CUT);
  _imp_READ(/*?*/ &LIMIT);

  //    71        ->L2 %IF 0<=CUT<=52

  {
    // Double-sided test on CUT (Part I)
    int tmp;
    if (0 > (tmp = CUT)) goto L_0023;
    // Double-sided test on CUT (Part II)
    if (tmp > 52) goto L_0023;
  }
  goto U_1002;
L_0023:;

//    72        print string( "INVALID CUT"); %STOP

  _imp_PRINTSTRING(_imp_str_literal("INVALID CUT"));
  _imp_stop(0);

  //    73  L2:   SHUFFLE; SHUFFLE; SHUFFLE; SHUFFLE

U_1002:;
  SHUFFLE();
  SHUFFLE();
  SHUFFLE();
  SHUFFLE();

  //    74  L1:   SHUFFLE; DEALPACK

U_1003:;
  SHUFFLE();
  DEALPACK();

  //    75        %BEGIN; ! BIDDING BLOCK

  { /*%begin*/

    //    76           %INTEGER LS,NO,SUITPTS

    int LS;
    int NO;
    int SUITPTS;

    //    77                    %SWITCH B(0:20)

    int B_index;
    int B_line;
    char *B_file;
    static const void *B[21] = {
        &&case_B_0,       &&case_B_1,       &&case_B_2,       &&case_B_3,       &&case_B_missing, &&case_B_missing,
        &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing,
        &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing, &&case_B_missing,
        &&case_B_missing, &&case_B_missing, &&case_B_missing};

    //    78           %INTEGER I,N

    int I;
    int N;

    //    79           %ROUTINE BIDSUIT(%INTEGER I)

    void BIDSUIT(int I) {
      //    80              WRITE(I,1); SPACE; PRINTSYMBOL(S(LS))

      _imp_WRITE(I, 1);
      _imp_SPACE();
      _imp_PRINTSYMBOL(S[LS]);

      //    81              %END

      return;
    } /* end of BIDSUIT */

    //    82
    //    83           %ROUTINE NT(%INTEGER I)

    void NT(int I) {
      //    84              WRITE(I,1); print string(" NT")

      _imp_WRITE(I, 1);
      _imp_PRINTSTRING(_imp_str_literal(" NT"));

      //    85              %END

      return;
    } /* end of NT */

    //    86
    //    87           NO=3

    NO = 3;

    //    88           %CYCLE I=0,1,3

    // %for I = 0, 1, 3 %cycle
    {
      I = -1;
    L_0024:
      if (I == 3) goto L_0025;
      I += 1;

      //    89              %IF DIST(I)>NO %THENSTART

      if (DIST[I] <= NO) goto L_0026;

        //    90                 LS=I; NO=DIST(I)

      LS = I;
      NO = DIST[I];

      //    91                 %FINISH; %REPEAT

    L_0026:;
      goto L_0024;
    }

  L_0025:;

  //    92           %IF LS=0 %AND DIST(3)=NO %THEN LS=3

    if (LS != 0) goto L_0027;
    if (DIST[3] != NO) goto L_0027;
    LS = 3;
  L_0027:;

  //    93           SUITPTS=PTS(LS)+5*(NO-4); SPACES(18)

    SUITPTS = PTS[LS] + 5 * (NO - 4);
    _imp_SPACES(18);

    //    94           N=BALANCE; %IF N>3 %THEN BALANCE=3

    N = BALANCE;
    if (N <= 3) goto L_0028;
    BALANCE = 3;
  L_0028:;

  //    95           ->B(BALANCE)

    B_line = __LINE__;
    B_file = __FILE__;
    B_index = BALANCE;
    goto case_B_dispatch;

    //    96     B(0): ->L2 %IF POINTS>=12

  case_B_0:;
    if (POINTS < 12) goto L_002A;
    goto U_1004;
  L_002A:;

  //    97     NB:            print string(" NO BID"); ->L1

  U_1005:;
    _imp_PRINTSTRING(_imp_str_literal(" NO BID"));
    goto U_1006;

    //    98    L2:     %IF POINTS<=15 %THENSTART

  U_1004:;
    if (POINTS > 15) goto L_002B;

      //    99               ->L3 %IF SUITPTS>10

    if (SUITPTS <= 10) goto L_002C;
    goto U_1007;
  L_002C:;

  //   100               NT(1); ->L1; %FINISH

    NT(1);
    goto U_1006;
  L_002B:;

  //   101            %IF POINTS<20 %THENSTART

    if (POINTS >= 20) goto L_002D;

      //   102        L3:    BIDSUIT(1); ->L1; %FINISH

  U_1007:;
    BIDSUIT(1);
    goto U_1006;
  L_002D:;

  //   103            %IF POINTS>=23 %THEN ->TC

    if (POINTS < 23) goto L_002E;
    goto U_1008;
  L_002E:;

  //   104            %IF SUITPTS>=15 %THEN BIDSUIT(2) %ELSE NT(2)

    if (SUITPTS < 15) goto L_002F;
    BIDSUIT(2);
    goto L_0030;
  L_002F:;
    NT(2);
  L_0030:;

  //   105            ->L1

    goto U_1006;

    //   106     B(1):  %IF POINTS=11 %AND SUITPTS>10 %THEN ->L3

  case_B_1:;
    if (POINTS != 11) goto L_0031;
    if (SUITPTS <= 10) goto L_0031;
    goto U_1007;
  L_0031:;

  //   107            ->NB %IF POINTS<=11

    if (POINTS > 11) goto L_0032;
    goto U_1005;
  L_0032:;

  //   108            ->L3 %IF POINTS<=18

    if (POINTS > 18) goto L_0033;
    goto U_1007;
  L_0033:;

  //   109            ->L7 %IF POINTS<22

    if (POINTS >= 22) goto L_0034;
    goto U_1009;
  L_0034:;

  //   110     TC:    print string(" 2 C(ACOL)"); ->L1

  U_1008:;
    _imp_PRINTSTRING(_imp_str_literal(" 2 C(ACOL)"));
    goto U_1006;

    //   111     B(2):  ->PR %IF POINTS<10

  case_B_2:;
    if (POINTS >= 10) goto L_0035;
    goto U_100A;
  L_0035:;

  //   112            ->L6 %IF POINTS>=12

    if (POINTS < 12) goto L_0036;
    goto U_100B;
  L_0036:;

  //   113            ->L3 %IF SUITPTS>10; ->NB

    if (SUITPTS <= 10) goto L_0037;
    goto U_1007;
  L_0037:;
    goto U_1005;

    //   114     B(3):  ->PR %IF POINTS<8

  case_B_3:;
    if (POINTS >= 8) goto L_0038;
    goto U_100A;
  L_0038:;

  //   115    L6:     ->L3 %IF POINTS<=18-N

  U_100B:;
    if (POINTS > 18 - N) goto L_0039;
    goto U_1007;
  L_0039:;

  //   116            ->TC %IF POINTS>=22-N

    if (POINTS < 22 - N) goto L_003A;
    goto U_1008;
  L_003A:;

  //   117    L7:     %IF SUITPTS>15 %THEN I=2 %ELSE I=1

  U_1009:;
    if (SUITPTS <= 15) goto L_003B;
    I = 2;
    goto L_003C;
  L_003B:;
    I = 1;
  L_003C:;

  //   118            ->L8

    goto U_100C;

    //   119     PR:    SUITPTS=5*(NO-4)+POINTS

  U_100A:;
    SUITPTS = 5 * (NO - 4) + POINTS;

    //   120            ->NB %IF SUITPTS <=20; ->L9 %IF LS<2

    if (SUITPTS > 20) goto L_003D;
    goto U_1005;
  L_003D:;
    if (LS >= 2) goto L_003E;
    goto U_100D;
  L_003E:;

  //   121    L9:     %IF SUITPTS<=27 %THEN I=3 %ELSE I=4

  U_100D:;
    if (SUITPTS > 27) goto L_003F;
    I = 3;
    goto L_0040;
  L_003F:;
    I = 4;
  L_0040:;

  //   122            ->NB %IF SUITPTS <=22

    if (SUITPTS > 22) goto L_0041;
    goto U_1005;
  L_0041:;

  //   123            %IF SUITPTS >30 %THENSTART

    if (SUITPTS <= 30) goto L_0042;

      //   124               I=5; ->L8; %FINISH

    I = 5;
    goto U_100C;
  L_0042:;

  //   125    L8:     BIDSUIT(I)

  U_100C:;
    BIDSUIT(I);

    //   126    L1:     %END; ! OF BIDDING BLOCK

  U_1006:;
    goto end_1000;

  case_B_dispatch:
    if (B_index < 0 || B_index > 20)
      _imp_signalf(6, 3, B_index, "->B(%d) out of bounds at %s line %d", B_index, B_file, B_line);
    goto *B[B_index - 0];

  case_B_missing:
    _imp_signalf(8, 2, B_index, "switch jump to undefined label B(%d): at %s line %d", B_index, B_file, B_line);
  end_1000:;
  }

  //   127
  //   128                   NEWLINES(3)

  _imp_NEWLINES(3);

  //   129         ->L1 %IF HANDCOUNT<LIMIT

  if (HANDCOUNT >= LIMIT) goto L_0043;
  goto U_1003;
L_0043:;

//   130         %ENDOFPROGRAM

  _imp_stop(0);
  return 0;
end_0:;
}