program Lora;
{verze 1.01; 2008-03-01}
{c 2008 Rudolf Rosa <rur@seznam.cz>, Matematicko-fyzik ln¡ fakulta Univerzita Karlova v Praze, 1. roŸ., zimn¡ semestr, programov n¡(IP), studium prezenŸn¡ bakal ýsk‚, ID studia: 237976}
{z poŸtovì program - NPRG030 - Programov n¡ I - Doc. RNDr. T”pfer Pavel, CSc.}
{ofici ln¡ Pravidla L¢ry viz http://www.volny.cz/petasites/Pravidla_Lory.htm}
{k¢dov n¡ Ÿeçtiny: CP852 (PC Latin 2); doporuŸenì kompil tor: Free Pascal Compiler}
{opensource}

uses crt;

{###############
TYPE, CONST, VAR
###############}

type MiniPoleChar   = array [0..3] of char; {pro ulo§en¡ n zv… barev}
     MalePoleChar   = array [0..7] of char; {pro ulo§en¡ n zv… karet}
     KartaChar      = string [2]; {znakov‚ oznaŸen¡ karty}
     MiniPoleByte   = array [0..3] of byte; {4 karty/skore/...}
     MalePoleByte   = array [0..7] of byte; {pro 8 karet}
     VsechnyKarty   = array [0..31] of byte; {pro vçechny karty}
     KartyPoCtyrech = array [0..3] of MalePoleByte; {pro vçechny karty ve 4 skupink ch}
     
     KartyM         = set of 0..31; {mno§ina pro karty}
     KartyPoCtyrechM= array [0..3] of KartyM; {mno§ina pro karty pro 4 hr Ÿe}
     
     Hry            = (C,F,P,V,B,Q,D,M);

const Barvy:   MiniPoleChar = ('Ÿ','k','z','§');  {Ÿerven‚, kule, zelen‚, §aludy}
      Karty:   MalePoleChar = ('7','8','9','X','S','F','K','E');  {sedma, osma, dev¡tka, des¡tka, spodek, filek, kr l, eso}
      BarvyId: MiniPoleByte = (LightRed, LightMagenta, LightGreen, Brown);
      BarvyPrg:MiniPoleByte = (Black, Brown, Blue, White); {barvy programu: text; pozad¡; pozad¡ karty; lad¡c¡ informace}
      HraNazev: array [C..M] of string[16] = ('Ÿerven‚','filky','prvn¡ - posledn¡','vçechny','Ÿervenì kr l','kvarty','des¡tky','maturita');
      
      KartyPodleBarevM:     KartyPoCtyrechM = ([0,4, 8,12,16,20,24,28],[1,5, 9,13,17,21,25,29],[2,6,10,14,18,22,26,30],[3,7,11,15,19,23,27,31]); {mno§iny karet podle barev}
      KartyNecerveneM:      KartyM = [1,2,3,5,6,7,9,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31];
      KartyFilkyM:          KartyM = [20..23];
      KartyDivokaKartaM:    KartyM = [20..31];  {v Qart ch - § dn  ni§ç¡ karta ne§ F}
      
      LADENI = false;  {standardnØ false; pokud je true, vypisuje r…zn‚ dalç¡ informace}
      ZIVYHRAC = 1;  {standardnØ 1 (Ÿek  se na vstup u§ivatele); 2: hraje za nØj random; 3: hraje za nØj UI}

var Balicek: VsechnyKarty; {vçechny karty v bal¡Ÿku}
    Rozdani: KartyPoCtyrech; {karty hr Ÿ… 0~3}
    RozdaniM: KartyPoCtyrechM; {karty hr Ÿ… 0~3 jako mno§iny}
    KartyZahraneM: KartyM; {vçechny karty, kter‚ u§ jsou na stole}
    Stych: MiniPoleByte; {aktu ln¡ çtych (karty le§¡c¡ na stole)}
    KartyVynesitelne: MalePoleByte; {karty, kter‚ m…§e Hrac vyn‚st}
    KartyVynesitelnePocet: byte; {poŸet karet v KartyVynesitelne}
    Pakl: VsechnyKarty; {odehran‚ karty pýed hr Ÿem, otoŸen‚ reversem vzh…ru (çtychy kter‚ hr Ÿ sebral; zar §ka = hodnota 32)}
    
    Talie, {0~3}
    Vynos, {pokolik t‚ se pr vØ v d¡lŸ¡ hýe vyn ç¡ (0~7)}
    Karta, {karta, se kterou se pr vØ pracuje}
    Hrac, HracPoradi, HracVynasejici: byte; {ten, kterì pr vØ hraje; jako kolik tì hraje Hrac (vyn çej¡c¡ hr Ÿ m  poýad¡ 0); ten, kterì vyn çej¡/vyn çel}
    HracClovek: byte;  {kterì hr Ÿ je ŸlovØk; mo§nosti: 0, 1, 2, 3}
    PocetKaret: MiniPoleByte; {kolik m  hr Ÿ v ruce karet}
    
    SkoreCelkove, SkoreHra, CistaStovka : MiniPoleByte; {sk¢re jednotlivìch hr Ÿ…; sk¢re jednotlivìch hr Ÿ… z¡skan‚ v aktu ln¡ hýe; zda hr Ÿi jdou na Ÿistou stovku}
    SkoreStych, {bodov‚ ohodnocen¡ aktu ln¡ho çtychu}
    StychBarva: byte; {barva çtychu}
    StychMaxTyp, StychMaxHrac: byte; {nejvyçç¡ vynesen  karta (barvy StychBarva) a kdo ji vynesl}
    
    Hra: Hry; {aktu ln¡ hra; pokud se hraje maturita: hra zvolen  maturantem}
    Maturita: byte; {0 - nehraje se maturita; 1~3: kolik tì pokus}
    
    log: text; {log hry}

{###################
PROCEDUTRY A FUNKCE
###################}

procedure ok; {procedura pro ladØn¡ - nen¡ souŸ st¡ programu}
  begin
    writeln('ok');
  end;

function abs(cislo: integer):byte;
  begin
    if cislo<0 then cislo:=-cislo;
    abs:=cislo;
  end;

function karta2char(Karta: byte): KartaChar;
  begin
    if Karta=32 then karta2char:='__' else
    karta2char:=Barvy[Karta mod 4]+Karty[Karta div 4];
  end;
  
function vyJa(Hrac: byte): string[5];
  {je-li Hrac ŸlovØk, vrac¡ VY, jinak PC (p…vodnØ Jµ, odtud n zev procedury)}
  begin
    if Hrac=HracClovek then vyJa:=' (VY)' else vyJa:=' (PC)';
  end;

procedure zvuk;
  begin
    Sound(100); Delay(100); NoSound;
  end;

procedure cekejNaStisk;
  begin
    if ZIVYHRAC=1 then repeat readkey until not KeyPressed;  {Ÿek  a§ user stiskne a pust¡ kl vesu}
  end;

procedure nulujPole(var Pole: array of byte);
  {nastav¡ vçechny hodnoty v poli na 0}
  var i: byte;
  begin
    for i := 0 to High(Pole) do Pole[i] := 0;
  end;

{VYPISOVµNÖ}
procedure writeKarta(Karta:byte);
  {vyp¡çe na obrazovku kartu}
  begin
    TextBackground(BarvyPrg[2]); TextColor(BarvyId[Karta mod 4]);
    write(karta2char(Karta));
    write(log,karta2char(Karta));
    TextBackground(BarvyPrg[1]); TextColor(BarvyPrg[0]);
    write(' ');
    write(log,' ');
  end;
  
procedure vypisKarty(Pole: MalePoleByte; Pocet: byte; VypisovatCislo: boolean);
  {vyp¡çe [Pocet] karet v poli}
  var i:byte;
  begin
    if Pocet>0 then for i := 0 to (Pocet-1) do begin
      if VypisovatCislo then write(i+1,':');
      writeKarta(Pole[i]);
    end;
  end;

procedure doplnMezerami;
  {vyp¡çe mezery a§ do konce aktu ln¡ho ý dku}
  var i: byte;
  begin
  for i:= WhereX to 80 do write(' ');
  end;
  
type Zpravy = (HrajeteJako, InformaceNaZacatkuStychu, InformaceNaZacatkuStychuQ, InformaceNaZacatkuHryD, KartaNesenaHracem, KartaNesenaHracemD, TukD, KonecStychu, KonecStychuQ, InfoSkore, Cista100, Cista100Info, MaturitaVyber, MaturitaVyberInfo, VyberteKartu, NevynasetDalsi, InfoPakl, NaTuhleSeKouka, VitezstviQ, VitezstviD, MaturantNeodmaturoval, Bedrnik, KonecLory);

procedure vypisZpravu(Typ: Zpravy);
  var i:byte;
  begin
    case Typ of
      HrajeteJako: begin
        writeln('Hrajete jako hr Ÿ ',HracClovek,'. Pro spuçtØn¡ hry stisknØte libovolnou kl vesu.');
      end;
      InformaceNaZacatkuStychu: begin
        write('Hraje se ',Talie+1,'. t lie, ');
        writeln(log); if Vynos=0 then write(log,'Hraje se ',Talie+1,'. t lie, ');
        if Maturita>0 then write(Maturita,'. maturita hr Ÿe ',Talie,vyJa(Talie),', ');
        if Maturita>0 then write(log,Maturita,'. maturita hr Ÿe ',Talie,', ');
        writeln('hra ',HraNazev[Hra]); writeln;
        if Vynos=0 then writeln(log,'hra ',HraNazev[Hra]);
        if LADENI then begin {vypiç karty hr Ÿ…} for i:= 0 to 3 do begin write('Hr Ÿ ',i,vyJa(i),': ',PocetKaret[i],' '); vypisKarty(Rozdani[i],PocetKaret[i],false); writeln; end; end;
        write('Vaçe karty:  ');
        write(log,'Vaçe karty:  ');
        vypisKarty(Rozdani[HracClovek],PocetKaret[HracClovek],false); {vyp¡çe karty hr Ÿe HracClovek}
        writeln; writeln; writeln(log);
        vypisZpravu(InfoPakl);
        writeln; writeln;
        writeln(Vynos+1,'. çtych, vyn ç¡ Hr Ÿ ',HracVynasejici,vyJa(HracVynasejici)); writeln;
        writeln(log,Vynos+1,'. çtych, vyn ç¡ Hr Ÿ ',HracVynasejici); 
      end;
      InformaceNaZacatkuStychuQ: begin
        write('Hraje se ',Talie+1,'. t lie, ');
        writeln(log); write(log,'Hraje se ',Talie+1,'. t lie, ');
        if Maturita>0 then write(Maturita,'. maturita hr Ÿe ',Talie,vyJa(Talie),', ');
        writeln('hra ',HraNazev[Hra]); writeln;
        writeln(log,'hra ',HraNazev[Hra]); 
        writeln('PoŸty karet hr Ÿ…:');
        if LADENI then begin {vypiç karty hr Ÿ…} for i:= 0 to 3 do begin write('Hr Ÿ ',i,vyJa(i),': ',PocetKaret[i],' '); vypisKarty(Rozdani[i],PocetKaret[i],false); writeln; end; end else begin
        for i:= 0 to 3 do writeln('Hr Ÿ ',i,vyJa(i),': ',PocetKaret[i]); writeln; end;
        write('Vaçe karty:  ');
        write(log,'Vaçe karty:  ');
        vypisKarty(Rozdani[HracClovek],PocetKaret[HracClovek],false); {vyp¡çe karty hr Ÿe HracClovek}
        writeln; writeln; writeln(log);
        vypisZpravu(InfoPakl);
        writeln; writeln;
        writeln('Vyn ç¡ Hr Ÿ ',HracVynasejici,vyJa(HracVynasejici)); writeln;
        writeln(log,'Vyn ç¡ Hr Ÿ ',HracVynasejici); 
      end;
      InformaceNaZacatkuHryD: begin
        write('Hraje se ',Talie+1,'. t lie, ');
        writeln(log); write(log,'Hraje se ',Talie+1,'. t lie, ');
        if Maturita>0 then write(Maturita,'. maturita hr Ÿe ',Talie,vyJa(Talie),', ');
        writeln('hra ',HraNazev[Hra]); writeln;
        writeln(log,'hra ',HraNazev[Hra]); 
        writeln('PoŸty karet hr Ÿ…:');
        if LADENI then begin {vypiç karty hr Ÿ…} for i:= 0 to 3 do begin write('Hr Ÿ ',i,vyJa(i),': ',PocetKaret[i],' '); vypisKarty(Rozdani[i],PocetKaret[i],false); writeln; end; writeln; end else begin
        for i:= 0 to 3 do writeln('Hr Ÿ ',i,vyJa(i),': ',PocetKaret[i]); writeln; end;
        write('Vaçe karty:  ');
        write(log,'Vaçe karty:  ');
        vypisKarty(Rozdani[HracClovek],PocetKaret[HracClovek],false); {vyp¡çe karty hr Ÿe HracClovek}
        writeln(log);
        GotoXY(1,21);
        for i:= 0 to 3 do writeln('Hr Ÿ ',i,vyJa(i),': ');
      end;
      KartaNesenaHracem: begin
        write('Hr Ÿ ',Hrac,vyJa(Hrac),': ');
        write(log,'Hr Ÿ ',Hrac,': ');
        writeKarta(Karta);
        writeln; writeln(log);
      end;
      KartaNesenaHracemD: begin
        {karta na st…l}
        write(log,'Hr Ÿ ',Hrac,': ');
        GotoXY( (2 + (Karta div 4)*3) , (13 + (Karta mod 4)*2) );
        writeKarta(Karta);
        {poŸet karet hr Ÿe}
        GotoXY(14,(4+Hrac));
        write(PocetKaret[Hrac]);
        if LADENI then begin {vyp¡çe karty hr Ÿe} write(' ');vypisKarty(Rozdani[Hrac],PocetKaret[Hrac],false); doplnMezerami; end;
        {kdo co vynesl}
        write(log,'Hr Ÿ ',Hrac,': ');
        GotoXY(14+Vynos*3,21+Hrac);
        writeKarta(Karta);
        doplnMezerami; writeln(log);
        {karty ŸlovØka}
        if Hrac=HracClovek then begin
          GotoXY(14,9);
          write(log,'Vaçe karty: ');
          vypisKarty(Rozdani[HracClovek],PocetKaret[HracClovek],false); {vyp¡çe karty hr Ÿe HracClovek}
          writeln(log);
          doplnMezerami;
        end;
      end;
      TukD: begin {œuk}
        GotoXY(14,21+Hrac);
        write('œuk');
        doplnMezerami;
        writeln(log,'Hr Ÿ ',Hrac,': œuk');
      end;
      KonecStychu: begin
        writeln; writeln;
        write(Vynos+1,'. çtych bere hr Ÿ ',StychMaxHrac,vyJa(StychMaxHrac),' a ');
        case SkoreStych of
          0: write ('nedost v  za nØj § dn‚ trestn‚ body.');
          1: write ('dost v  za nØj 1 trestnì bod.');
          2..4: write ('dost v  za nØj ',SkoreStych,' trestn‚ body.');
          5..99: write ('dost v  za nØj ',SkoreStych,' trestnìch bod….');
        end;
        write(log,Vynos+1,'. çtych bere hr Ÿ ',StychMaxHrac,'. PoŸet z¡skanìch trestnìch bod…: ',SkoreStych); writeln(log); 
      end;
      KonecStychuQ: begin
        writeln; writeln;
        writeln('Tento çtych bere hr Ÿ ',StychMaxHrac,vyJa(StychMaxHrac),'.');
        writeln(log,'Tento çtych bere hr Ÿ ',StychMaxHrac,'.');
        writeln;
      end;
      InfoSkore: begin
        zvuk;
        writeln;
        if (Maturita <> 0) AND (SkoreHra[Talie]=0) then writeln('Hr Ÿ ',Talie,vyJa(Talie),' odmaturoval! Gratuluji!');
        cekejNaStisk;
        clrscr;
        writeln; writeln('Sk¢re:');
        for i:= 0 to 3 do writeln('Hr Ÿ ',i,vyJa(i),': v t‚to hýe: ',SkoreHra[i],', celkem: ',SkoreCelkove[i],' ');
        writeln(log); writeln(log,'Sk¢re:');
        for i:= 0 to 3 do writeln(log,'Hr Ÿ ',i,': v t‚to hýe: ',SkoreHra[i],', celkem: ',SkoreCelkove[i],' ');
        writeln;
      end;
      Cista100: begin
        clrscr;
        writeln; write('Chcete nahl sit Ÿistou stovku?   0:Ne  1:Ano');
      end;
      Cista100Info: begin
        writeln; writeln;
        write('Hr Ÿ ',HracClovek,vyJa(HracClovek),' ');
        if CistaStovka[HracClovek]=0 then write('ne');
        write('nahl sil Ÿistou stovku.')
      end;
      MaturitaVyber: begin  {Maturant m…§e vybrat: C, F, V, B, Q, D. Pýi týet¡ maturitØ m…§e i P.}
        cekejNaStisk;
        clrscr;
        writeln;
        write(' Vaçe karty:  ');
        vypisKarty(Rozdani[HracClovek],PocetKaret[HracClovek],false); {vyp¡çe karty hr Ÿe HracClovek}
        writeln; writeln; writeln(' Vyberte hru pro maturitu:'); writeln;
        Hra := C;
        for Hra:= C to D do begin
          if (Hra<>P) OR (Maturita = 3) then begin writeln(' ',(ord(Hra)+1),': ',HraNazev[Hra]); writeln; end;   {pýi týet¡ maturitØ sm¡ hr Ÿ vybrat cokoliv, jinak nesm¡ vybrat P}
        end;
      end;
      MaturitaVyberInfo: begin  {Maturant m…§e vybrat: C, F, V, B, Q, D. Pýi týet¡ maturitØ m…§e i P.}
        writeln; writeln; writeln(' Byla vybr na hra ',HraNazev[Hra],'.');
        writeln(log,' Byla vybr na hra ',HraNazev[Hra],'.');  
      end;
      VyberteKartu: begin
        if Hra=D then GotoXY(1,11);
        write('>Vyberte kartu:   ');
      end;
      NevynasetDalsi: begin
        write('0: nevyn çet dalç¡');
      end;
      InfoPakl: begin
        write('V ç pakl: ');
        write(log,'V ç pakl: ');
        i := 0;
        while Pakl[i]<>32 do begin
          writeKarta(Pakl[i]);
          inc(i);
        end;
        writeln;
      end;
      NaTuhleSeKouka: begin
        writeln('Na tuhle kartu se kouk !');
        writeln(log,'Na tuhle kartu se kouk !');
      end;
      VitezstviQ: begin
        writeln('V¡tØzem tØchto kvaret se st v  Hr Ÿ ',Hrac,vyJa(Hrac),'.');
        writeln(log,'V¡tØzem tØchto kvaret se st v  Hr Ÿ ',Hrac,'.');
      end;
      VitezstviD: begin
        GotoXY(1,11);
        if PocetKaret[Hrac]=0 then begin
          writeln('Hr Ÿ ',Hrac,vyJa(Hrac),' zavýel!');
          doplnMezerami;
          writeln(log,'Hr Ÿ ',Hrac,' zavýel!');
        end;
      end;
      MaturantNeodmaturoval: begin
        writeln;
        if Hra=D then GotoXY(1,11);
        writeln('Hr Ÿ ',Talie,vyJa(Talie),' neodmaturoval!');
        writeln('Hr Ÿ ',Talie,' dost v  8 trestnìch bod…, ostatn¡ hr Ÿi jsou bez trestnìch bod….');
        writeln(log,'Hr Ÿ ',Talie,' neodmaturoval! Hr Ÿ ',Talie,' dost v  8 trestnìch bod…, ostatn¡ hr Ÿi jsou bez trestnìch bod….');
        writeln;
      end;
      Bedrnik: begin
        writeln;
        writeln('Ve çtychu byl Bedrn¡k! Hr Ÿ ',StychMaxHrac,vyJa(StychMaxHrac),' dost v  8 trestnìch bod….');
        if Vynos=0 then writeln('F………j, Bedrn¡k v prvn¡m çtychu!!!');  {to je nesportovn¡ gesto}
        writeln(log,'Ve çtychu byl Bedrn¡k! Hr Ÿ ',StychMaxHrac,' dost v  8 trestnìch bod….');
        writeln;
      end;
      KonecLory: begin
        zvuk; zvuk; zvuk;
        clrscr;
        writeln; writeln('Konec hry!');
        writeln; writeln('KoneŸn‚ sk¢re:');
        writeln(log); writeln(log); writeln(log,'Konec hry! KoneŸn‚ sk¢re:');
        for i:= 0 to 3 do begin
          writeln;
          write('Hr Ÿ ',i,vyJa(i),': ',SkoreCelkove[i]);
          if CistaStovka[i]=1 then begin
            write(' (Ÿist  stovka - ');
            if SkoreCelkove[i]=100 then write('£spØçnØ!)') else write('ne£spØçnØ!)');
          end;
          writeln;
        end;
        for i:= 0 to 3 do writeln(log, 'Hr Ÿ ',i,vyJa(i),': ',SkoreCelkove[i]);
        writeln;
        cekejNaStisk;
        cekejNaStisk;
        writeln;
      end;
    end;
  end;

procedure zamichat;
  var i: integer;
      Karta,temp1,temp2: byte;
  begin
    for i := 0 to 1000 do
    begin {prohod¡ dvØ n hodn‚ karty}
      temp1:=random(32);
      temp2:=random(32);
      Karta:=Balicek[temp1];
      Balicek[temp1]:=Balicek[temp2];
      Balicek[temp2]:=Karta;
    end;
  end;

procedure rozdat;
  {rozd v  karty pýesnØ podle pravidel L¢ry, tedy po dvou}
  var Osmice, Barva, Typ, Karta: byte;
  begin
    for Hrac := 0 to 3 do RozdaniM[Hrac] := []; {mno§iny karet vçech hr Ÿ… jsou pr zdn‚}
    nulujPole(PocetKaret);
    {rozdat karty - do mno§in RozdaniM}
    for Osmice := 0 to 3 do begin {pro ka§dou osmici karet}
      for Hrac := 0 to 3 do RozdaniM[Hrac] := RozdaniM[Hrac] + [Balicek[Osmice*8 + Hrac*2],Balicek[Osmice*8 + Hrac*2 + 1]]; {rozd  hr Ÿi dvØ karty}
    end;
    {podle mno§in nastav¡ obsah pole Rozdani - tak aby v nØm karty byly setý¡dØny tak, jak je zvykem, tedy podle barvy (¬,K,Z,¦) a podle typu vzestupnØ}
    for Barva := 0 to 3 do begin
      for Typ := 0 to 7 do begin
        Karta := Typ*4+Barva; 
        for Hrac := 0 to 3 do begin
          if Karta in RozdaniM[Hrac] then begin
            Rozdani[Hrac][PocetKaret[Hrac]] := Karta; {d  kartu na prvn¡ volnou pozici v poli karet hr Ÿe}
            inc(PocetKaret[Hrac]);  {inkrementuje poŸet karet hr Ÿe}
          end;
        end;
      end;
    end;
  end;

procedure prihodit;
  {realizace pýihozen¡ karty Karta hr Ÿem Hrac, kterì hraje jako HracPoradi-tì}
  var i,j: byte;
  begin
    if Hra <> D then Stych[HracPoradi] := Karta; {karta se objevuje ve çtychu (u D nesmysl)}
    dec(PocetKaret[Hrac]);  {hr Ÿ m  o kartu m‚nØ}
    RozdaniM[Hrac]:=RozdaniM[Hrac]-[Karta];   {hr Ÿ pýich z¡ o kartu}
    KartyZahraneM:=KartyZahraneM+[Karta];   {karta je zahran }
    {pýerovn v n¡ - nechœ na pozic¡ch 0..PocetKaret[Hrac] jsou karty kter‚ hr Ÿ m }
    if PocetKaret[Hrac]>0 then begin  {pokud hr Ÿ nem  § dn‚ karty, nen¡ co pýerovn vat}
      i:=0;
      while Rozdani[Hrac][i] <> Karta do inc(i);  {i := pozice karty Karta v poli}
      for j:= i to (PocetKaret[Hrac]-1) do Rozdani[Hrac][j] := Rozdani[Hrac][j+1];  {karty za touto pozic¡ se posunou o jednu doleva}
    end;
  end;

function predchoziD(Karta: byte): byte;
  {vr t¡ kartu, kter  v des¡tk ch bezprostýednØ pýedch z¡ kartØ Karta, nebo hodnotu 32}
  begin
    case (Karta div 4) of
      0..2: predchoziD:=Karta+4;  {o jednu vyçç¡}
      3: predchoziD:=32;  {je to des¡tka => neexistuje pýedchoz¡ karta}
      4..7: predchoziD:=Karta-4;  {o jednu ni§ç¡}
    end;
  end;

procedure pridejDoPaklu (Kolik: byte);
  {pýid  do Pakl Kolik karet ze Stych}
  var Zacatek,i: byte;
  begin
    Zacatek:= 0; while Pakl[Zacatek]<>32 do inc(Zacatek); {Zacatek = pozice zar §ky}
    for i := 0 to (Kolik-1) do Pakl[Zacatek+i] := Stych[i]; {pýidat do Pakl i-tou kartu ze Stych}
    Pakl[Zacatek+Kolik]:=32; {nov  pozice zar §ky}
  end;

procedure pridejDoKartyVynesitelne (Karta: byte);
  {pýid  do KartyVynesitelne kartu Karta}
  begin
    KartyVynesitelne[KartyVynesitelnePocet]:=Karta;
    inc(KartyVynesitelnePocet);
  end;

procedure pridejDoKartyVynesitelneVsechny;
  {pýid  do KartyVynesitelne vçechny karty hr Ÿe Hrac}
  begin
    KartyVynesitelne:=Rozdani[Hrac];
    KartyVynesitelnePocet:=PocetKaret[Hrac];
  end;

function readNumberChar(min,max: byte):byte;
  {pýeŸte znak a udØl  z nØj Ÿ¡slo - znak mus¡ bìt vØtç¡ ne§ min a menç¡ ne§ max}
  var znak: char;
  begin
    znak:=' '; {inicializace}
    while ( ord(znak)-ord('0') < min ) OR ( ord(znak)-ord('0') > max ) do znak:=readkey;
    readNumberChar:= ord(znak)-ord('0');
  end;

procedure skorePrepocti;
  {pýepoŸ¡t n¡ celkov‚ho sk¢re - pýiŸten¡ sk¢re za danou hru}
  var Hrac: byte;
  begin
    for Hrac:= 0 to 3 do inc(SkoreCelkove[Hrac],SkoreHra[Hrac]);
  end;

procedure vyberHru;
  {ŸlovØk maturant vyb¡r  hru}
  var HraCislo, i: byte;
  begin
    if ZIVYHRAC=1 then begin
      vypisZpravu(MaturitaVyber);
      if Maturita=3 then HraCislo:=readNumberChar(1,7) else begin  {pýi týet¡ maturitØ sm¡ hr Ÿ vybrat cokoliv}
        repeat
          HraCislo:=readNumberChar(1,7);
        until (HraCislo <> 3); {hr Ÿ nesm¡ vybrat P}
      end;
      Hra:=C;
      for i := 2 to HraCislo do Hra:=succ(Hra);  {kolik t  hra, tolik t  hra}
      vypisZpravu(MaturitaVyberInfo);
    end else Hra:=B;
  end;

{################
UM·Lµ INTELIGENCE
################}

procedure UI;
  {hlavn¡ rozhodovac¡ procedura, vìstupem je Karta, kterou nese Hrac}
  var UIKarty: MalePoleByte;  {obsahuje "sk¢re" jednotlivìch karet - karta s nejvyçç¡m sk¢re bude vynesena}
      KartaPoradi,  {poýad¡ v poli KartyVynesitelne}
      i, temp, max, min: byte;
      {podminka: boolean;  podle potýeby podm¡nka pro nØco}   
  
  {UI - VNITüNÖ PROCEDURY A FUNKCE}
  
  procedure podlejzat;
    {podl‚z m (nechci br t çtych) - vyn ç¡m co nejvyçç¡ ni§ç¡, pý¡padnØ co nejni§ç¡ vyçç¡; jsem-li posledn¡ vyn çej¡c¡ a mus¡m-li çtych vz¡t, vyn ç¡m nejvyçç¡ co m…§u}
    var Karta, KartaPoradi: byte;
    begin
      for KartaPoradi := 0 to (KartyVynesitelnePocet-1) do begin
        Karta:=KartyVynesitelne[KartaPoradi];
        if (Karta div 4) < StychMaxTyp then begin  {podjlejzac¡ karta}
          UIKarty[KartaPoradi]:= 100+(Karta div 4);
          if (Hra=F) AND (Karta div 4 = 5) then inc(UIKarty[KartaPoradi],4);  {podl‚zt filkem}
          if (Hra=B) AND (Karta = 24) then inc(UIKarty[KartaPoradi],50);  {podl‚zt bedrn¡kem}
        end else begin  {pýelejzac¡ karta}
          UIKarty[KartaPoradi]:= 50;
          if HracPoradi=3 then inc(UIKarty[KartaPoradi],(Karta div 4))  {budu to muset vz¡t => klidnØ co nejvyçç¡ kartou}
          else dec(UIKarty[KartaPoradi],(Karta div 4));  {týeba mØ jeçtØ nØkdo pýeleze => d m tam co nejni§ç¡ kartu}
          if (Hra=F) AND (Karta div 4 = 5) then UIKarty[KartaPoradi]:= 0;  {filkem nepýelejzat}
          if (Hra=B) AND (Karta = 24) then UIKarty[KartaPoradi]:= 0;  {bedrn¡kem nepýelejzat}
        end;
      end;
    end;
  
  procedure ctitBarvu;
    {ct¡m barvu - pokud je to bezpeŸn‚, m…§u çtych vz¡t, jinak podlejz m}
    var Karta, KartaPoradi: byte;
    begin
      if (HracPoradi=3) AND (SkoreStych=0) then   {ve çtychu nen¡ trestn  karta a j  jsem posledn¡}
        for KartaPoradi := 0 to KartyVynesitelnePocet-1 do begin
          Karta:=KartyVynesitelne[KartaPoradi];
          if NOT (((Hra=F) AND (Karta div 4 = 5)) OR ((Hra=B) AND (Karta = 24))) then  {pokud karta nen¡ trestn }
            UIKarty[KartaPoradi]:= (KartyVynesitelne[KartaPoradi] div 4) + 1;  {m…§u s n¡ vz¡t çtych}
        end
      else podlejzat;  {çtych m…§e bìt trestnì => podlejz m}
    end;
  
  function pocetVlastnichNizsichKaret(Karta, max: byte): byte;
    {poŸet ni§ç¡ch karet, kter‚ m m v ruce; maxim lnØ do £rovnØ max (napý. 3 = pro F hled  S, X a 9)}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      while (Karta>3) and (max>0) do begin  {dokud nejsem na sedmiŸce}
        dec(max);
        dec(Karta,4); {o 1 ni§ç¡ karta}
        if (Karta in RozdaniM[Hrac]) then inc(vysledek); {Kartu m m v ruce}
      end;
      pocetVlastnichNizsichKaret:= vysledek;
    end;
  
  function pocetNizsichKaret(Karta, max: byte): byte;
    {poŸet ni§ç¡ch karet, kter‚ jsou jeçtØ ve hýe; maxim lnØ do £rovnØ max (napý. 3 = pro F hled  S, X a 9)}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      while (Karta>3) and (max>0) do begin  {dokud nejsem na sedmiŸce}
        dec(max);
        dec(Karta,4); {o 1 ni§ç¡ karta}
        if not (Karta in KartyZahraneM) then inc(vysledek); {Karta nebyla jeçtØ zahran }
      end;
      pocetNizsichKaret:= vysledek;
    end;
  
  function pocetVyssichKaret(Karta, max: byte): byte;
    {poŸet vyçç¡ch karet, kter‚ jsou jeçtØ ve hýe; maxim lnØ do £rovnØ max (napý. 3 = pro 9 hled  X, S a F)}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      while (Karta<28) and (max>0) do begin  {dokud nejsem na esu}
        dec(max);
        inc(Karta,4); {o 1 vyçç¡ karta}
        if not (Karta in KartyZahraneM) then inc(vysledek); {Karta nebyla jeçtØ zahran }
      end;
      pocetVyssichKaret:= vysledek;
    end;
  
  function pocetVlastnichVyssichKaret(Karta, max: byte): byte;
    {poŸet vyçç¡ch karet, kter‚ jsou jeçtØ ve hýe; maxim lnØ do £rovnØ max (napý. 3 = pro 9 hled  X, S a F)}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      while (Karta<28) and (max>0) do begin  {dokud nejsem na esu}
        dec(max);
        inc(Karta,4); {o 1 vyçç¡ karta}
        if (Karta in RozdaniM[Hrac]) then inc(vysledek); {Karta nebyla jeçtØ zahran }
      end;
      pocetVlastnichVyssichKaret:= vysledek;
    end;
  
  function pocetNizsichKaretVsech(Karta: byte): byte;
    begin
      pocetNizsichKaretVsech:=pocetNizsichKaret(Karta,7);
    end;
  
  function pocetNizsichKaretVsechCizich(Karta: byte): byte;
    begin
      pocetNizsichKaretVsechCizich:=pocetNizsichKaret(Karta,7) - pocetVlastnichNizsichKaret(Karta,7);
    end;
  
  function pocetVyssichKaretVsech(Karta: byte): byte;
    begin
      pocetVyssichKaretVsech:=pocetVyssichKaret(Karta,7);
    end;
  
  function pocetVyssichKaretVsechCizich(Karta: byte): byte;
    begin
      pocetVyssichKaretVsechCizich:=pocetVyssichKaret(Karta,7) - pocetVlastnichVyssichKaret(Karta,7);
    end;
  
  procedure nejlepsiKartaProVynos;
    {typicky chci vyn‚st co nejni§ç¡ kartu; z roveå nechci vyn‚st trestnou kartu nebo takovou kartu, §e by çtych nikdo nemohl vz¡t}
    var Karta, KartaPoradi: byte;
    begin
      for KartaPoradi := 0 to (KartyVynesitelnePocet-1) do begin
        Karta:=KartyVynesitelne[KartaPoradi];
        UIKarty[KartaPoradi] := 50 + 3*pocetVyssichKaretVsechCizich(Karta) - pocetNizsichKaretVsechCizich(KartyVynesitelne[KartaPoradi]);  {Ÿ¡m v¡ce je ve hýe vyçç¡ch karet, t¡m je pro mØ karta ni§ç¡, a naopak}
        if ( (Hra=F) AND ( (Karta div 4) = 5) ) OR ( (Hra=B) AND (Karta = 24) ) then dec(UIKarty[KartaPoradi],30);  {trestn  karta}
        if ((RozdaniM[Hrac]-[Karta]) * KartyPodleBarevM[Karta mod 4])=[] then inc(UIKarty[KartaPoradi],2);  {karta je jedin  sv‚ barvy}
      end;
    end;
  
  procedure zbavovatSeKaret;
    {typicky chci vyn‚st co nejvyçç¡ kartu; je-li trestn  nebo jedin  sv‚ barvy, t¡m l¡p}
    var Karta, KartaPoradi: byte;
    begin
      for KartaPoradi := 0 to (KartyVynesitelnePocet-1) do begin
        Karta:=KartyVynesitelne[KartaPoradi];
        UIKarty[KartaPoradi] := 50 + pocetNizsichKaretVsechCizich(Karta) - pocetVyssichKaretVsechCizich(KartyVynesitelne[KartaPoradi]);  {Ÿ¡m v¡ce je ve hýe vyçç¡ch karet, t¡m je pro mØ karta ni§ç¡, a naopak}
        if (Hra=C) AND (Karta mod 4 = 0) then inc(UIKarty[KartaPoradi],4);  {Ÿerven }
        if (Hra=F) AND (Karta div 4 = 5) then inc(UIKarty[KartaPoradi],4);  {filek}
        if (Hra=B) AND (Karta = 24) AND (Vynos <> 0) then inc(UIKarty[KartaPoradi],50);  {bedrn¡k}
        if (Hra=B) AND (Karta = 24) AND (Vynos = 0) then dec(UIKarty[KartaPoradi],30);  {bedrn¡k - nechci bìt nesportovn¡, proto ho neh z¡m do prvn¡ho çtychu}
        if (Hra=B) AND (Karta < 24) AND (Karta mod 4 = 0) then dec(UIKarty[KartaPoradi],30);  {nezbavuju se karet, kterìmi m…§u podl‚zt bedrn¡ka}
        if ((RozdaniM[Hrac]-[Karta]) * KartyPodleBarevM[Karta mod 4])=[] then inc(UIKarty[KartaPoradi],6);  {karta je jedin  sv‚ barvy}
      end;
    end;
  
  function DmuzuZavrit:boolean;
    {D - vyhod¡ true pokud Hrac m…§e zavý¡t, jinak false}
    var i,Karta:byte;
    begin
      for i := 0 to PocetKaret[Hrac] do begin
        Karta:=Rozdani[Hrac][i];
        if not ((Karta div 4 = 3) OR (predchoziD(Karta) in KartyZahraneM) OR (predchoziD(Karta) in RozdaniM[Hrac])) then begin  {pokud ne: karta je des¡tka / pýedchoz¡ ke kartØ je na stole / pý.k. ke k. m m v ruce}
          DmuzuZavrit:=false; {nem…§u zavý¡t}
          exit; {ukonŸen¡ funkce}
        end;
      end;
      DmuzuZavrit:= true;  {cyklus nebyl ukonŸen => m…§u zavý¡t}
    end;
  
  function DzavislostP(Karta: byte):byte;
    {D - nejvyçç¡ karta z visl  zprava na kartØ Karta: 0 = nen¡, 1..4 = S..E}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      inc(Karta,4); {n selduj¡c¡ karta}
      while Karta<32 do begin  {dokud nejsem za esem}
        if Karta in RozdaniM[Hrac] then vysledek:= (Karta div 4) - 3; {hr Ÿ m  kartu Karta - vìsledek = normalizovanì typ}
        inc(Karta,4);
      end;
      DzavislostP:= vysledek;
    end;
  
  function DzavislostL(Karta: byte):byte;
    {D - nejni§ç¡ karta z visl  zleva na kartØ Karta: 0 = nen¡, 1..3 = 9..7}
    var vysledek: byte; {mezivìsledek}
    begin
      vysledek:=0;
      while Karta>3 do begin  {dokud nejsem na sedmiŸce}
        dec(Karta,4); {n sleduj¡c¡ karta}
        if Karta in RozdaniM[Hrac] then vysledek:= 3 - (Karta div 4); {hr Ÿ m  kartu Karta - vìsledek = normalizovanì typ}
      end;
      DzavislostL:= vysledek;
    end;
  
  function Dzavislost(Karta: byte):byte;
    {D - existuje z visl  karta?}
    begin
      case (Karta div 4) of
        0..2: Dzavislost := DzavislostL(Karta);  {7..9}
        3: Dzavislost := DzavislostL(Karta)+DzavislostP(Karta);  {X}
        4..7: Dzavislost := DzavislostP(Karta);  {S..E}
      end;
    end;
  
  
  {UI - VLASTNÖ T·LO PROCEDURY}
  begin
    {inicializace}
    nulujPole(UIKarty);
    if (Hra=D) AND (Vynos>0) then begin   {nav¡c mo§nost nevyn‚st nic}
      KartyVynesitelne[KartyVynesitelnePocet]:=32;
      inc(KartyVynesitelnePocet);
    end;
    if KartyVynesitelnePocet=1 then begin    {nen¡ z Ÿeho vyb¡rat}
      Karta:=KartyVynesitelne[0];
      exit;
    end;
    {rozliçen¡ podle her}
    case Hra of
      
      {¬ERVENí}
      C: begin
        if HracPoradi=0 then nejlepsiKartaProVynos {vyn ç¡m}
        else if (KartyVynesitelne[0] mod 4 = StychBarva) then ctitBarvu {pýihazuju barvu}
             else zbavovatSeKaret  {nem m barvu}
      end;
      
      {FILKY}
      F: begin
        if HracPoradi=0 then nejlepsiKartaProVynos {vyn ç¡m}
        else if (KartyVynesitelne[0] mod 4 = StychBarva) then ctitBarvu {pýihazuju barvu}
             else zbavovatSeKaret  {nem m barvu}
      end;
      
      {PR-PO}
      P: begin
        if Vynos in [1..4] then zbavovatSeKaret  {nebezepeŸ¡ nen¡ velk‚, m…§u hr t divoŸeji}
        else begin  {hraju standardnØ - nechci br t çtychy}
          if HracPoradi=0 then nejlepsiKartaProVynos {vyn ç¡m}
          else if (KartyVynesitelne[0] mod 4 = StychBarva) then ctitBarvu {pýihazuju barvu}
               else zbavovatSeKaret  {nem m barvu}
        end;
      end;
      
      {VæECHNY}
      V: begin
        if HracPoradi=0 then nejlepsiKartaProVynos {vyn ç¡m}
        else if (KartyVynesitelne[0] mod 4 = StychBarva) then ctitBarvu {pýihazuju barvu}
             else zbavovatSeKaret  {nem m barvu}
      end;
      
      {BEDRNÖK}
      B: begin
        if HracPoradi=0 then nejlepsiKartaProVynos {vyn ç¡m}
        else if (KartyVynesitelne[0] mod 4 = StychBarva) then ctitBarvu {pýihazuju barvu}
             else zbavovatSeKaret  {nem m barvu}
      end;
      
      {KVARTY}
      Q: begin
        for KartaPoradi := 0 to KartyVynesitelnePocet-1 do begin
          temp:=KartyVynesitelne[KartaPoradi]+12;  {jdu od nejvyçç¡ mo§n‚ karty v potenci ln¡m çtychu, a§ najdu tu nejvyçç¡, kter  je jeçtØ ve hýe}
          while (temp>=32) OR (temp in KartyZahraneM) do dec(temp,4);  {karta by byla vyçç¡ ne§ E nebo u§ byla zahran ; a§ cyklus skonŸ¡, m m nejvyçç¡ kartu potenci ln¡ho çtychu}
          if temp in RozdaniM[Hrac] then UIKarty[KartaPoradi]:=100 {m m nejvyçç¡ kartu v potenci ln¡m çtychu, tak§e ho beru}
          else UIKarty[KartaPoradi]:=50; {tenhle çtych neberu}
          if (pocetVlastnichNizsichKaret(KartyVynesitelne[KartaPoradi],3) > 0)
            then dec(UIKarty[KartaPoradi],36)
            else dec( UIKarty[KartaPoradi] , 9*pocetNizsichKaret(KartyVynesitelne[KartaPoradi],3) );  {Ÿ¡m m‚nØ je ve hýe pýedch zej¡c¡ch karet, t¡m vØtç¡ m  karta pýednost}
          for i := 1 to 3 do
            if (KartyVynesitelne[KartaPoradi]+i*4 < 32) then
              if (KartyVynesitelne[KartaPoradi]+i*4 in RozdaniM[Hrac]) then
                inc(UIKarty[KartaPoradi],3) else dec(UIKarty[KartaPoradi]);  {Ÿ¡m v¡ce karet vezme karta s sebou, t¡m l¡p; Ÿ¡m v¡ce soupeýovìch karet, t¡m h…ý} 
        end;
      end;
      
      {DESÖTKY}
      D: begin
        if DmuzuZavrit then begin  {m…§u zavý¡t => poka§d‚ m…§u vyn‚st libovolnou kartu - tak proŸ ne tu nultou}
          Karta:=KartyVynesitelne[0];
          exit;
        end;
        for KartaPoradi := 0 to KartyVynesitelnePocet-1 do begin
          Karta:=KartyVynesitelne[KartaPoradi];
          if Karta div 4 = 3 then begin {karta je des¡tka}
            UIKarty[KartaPoradi] := Dzavislost(Karta);  {Ÿ¡m vzd lenØjç¡ z visl‚ karty, t¡m vØtç¡ sk¢re}
            if UIKarty[KartaPoradi]>0 then begin  {m m na n¡ z visl‚ karty}
              if (DzavislostL(Karta)>0) AND (DzavislostP(Karta)>0) then inc(UIKarty[KartaPoradi],40)  {oboustrann  z vislost}
              else inc(UIKarty[KartaPoradi],20);  {jednostrann  z vislost}
            end;
          end else begin
            if Karta = 32 then begin {"karta" je "nevyn çet dalç¡ kartu"}
              min := 8;
              for i := 0 to 3 do if (i<>Hrac) AND (PocetKaret[i]<min) then min:=PocetKaret[i];   {minim ln¡ poŸet karet ostatn¡ch hr Ÿ…}
              if min<3 then begin
                UIKarty[KartaPoradi] := 30; {nØkterì hr Ÿ u§ je bl¡zko zavýen¡ => chci se trochu zbavit karet}
              end else begin
                UIKarty[KartaPoradi] := 60; {hra se jeçtØ nebl¡§¡ ke konci => co nemus¡m, nevyn ç¡m}
              end;
            end else begin  {karta je norm ln¡ karta}
              if Dzavislost(Karta)>0 then begin  {na kartØ jsou z visl‚ jin‚ m‚ karty}
                UIKarty[KartaPoradi] := 100;
              end else begin   {na kartØ nen¡ § dn  moje karta z visl }
                if (Karta div 4 = 0) OR (Karta div 4 = 7) then UIKarty[KartaPoradi] := 50  {je to 7 nebo E}
                else UIKarty[KartaPoradi] := 10 + ((abs(Karta-14)-2) div 4); {sk¢re = 10 + (vzd lenost od X)}
              end;
            end;
          end;
        end;
      end;
    end;
    
    {vyber maximum}
    max:=0; {index maxima - pro zaŸ tek nechœ je to prvn¡ vynesiteln  karta}
    for i := 1 to (KartyVynesitelnePocet-1) do if (UIKarty[i] > UIKarty[max]) then max := i;
    Karta:=KartyVynesitelne[max];   {vyn‚st kartu s maxim ln¡m ohodnocen¡m}
    
    if LADENI then begin
      temp:=WhereY;
      gotoXY(1,25);
      TextColor(BarvyPrg[3]);
      for i := 0 to (KartyVynesitelnePocet-1) do write(karta2char(KartyVynesitelne[i]),':',UIKarty[i],' ');
      TextColor(BarvyPrg[0]);
      doplnMezerami;
      cekejNaStisk;
      gotoXY(1,temp);
    end;
  end;

{########
SRDCE HRY
########}

procedure hratManualne;
  {nechœ Hrac vybere kartu z KartyVynesitelne -> vìstup v Karta; 32 pokud u§ nechce hr t (D)}
  var i:byte;
  begin
    case ZIVYHRAC of
      1: begin
        vypisZpravu(VyberteKartu);
        vypisKarty(KartyVynesitelne,KartyVynesitelnePocet,true);

        if (Hra=D) AND (Vynos>0) then begin
          vypisZpravu(NevynasetDalsi);  {hr Ÿ u§ nØjakou kartu vynesl => nemus¡ ji§ vyn çet dalç¡}
          i:=readNumberChar(0,KartyVynesitelnePocet);
        end else i:=readNumberChar(1,KartyVynesitelnePocet);
        if i=0 then Karta:=32 else Karta:=KartyVynesitelne[i-1];
        GotoXY(1,WhereY);
        doplnMezerami;
        GotoXY(1,WhereY);
      end;
      2: Karta:=KartyVynesitelne[Random(KartyVynesitelnePocet)];
      3: UI;
    end;
  end;

procedure hratPrebijeci; {hr t nØjakou pýeb¡jec¡ hru - C, F, P, V, B}
var j: byte;
begin
  {CYKLUS PRO KA¦Dí VíNOS}
  for Vynos:= 0 to 7 do begin {bude se vyn çet 8x}
    {INICIALIZACE VíNOSU}
    cekejNaStisk;
    clrscr;
    vypisZpravu(InformaceNaZacatkuStychu);
    StychMaxTyp:=0; {jakoby sedmiŸka - urŸitØ nebude nejvyçç¡ karta ni§ç¡ ne§ 7}
    StychMaxHrac:=HracVynasejici; {nejvyçç¡ kartu nejdý¡v urŸitØ vynese prvn¡ hr Ÿ}
    {SkoreStych}
    SkoreStych:=0;
    if Hra in [P,V] then begin {trestn‚ body za çtych}
      case Hra of
        P: if (Vynos = 0) OR (Vynos = 7) then SkoreStych:=4; {prvn¡/posledn¡ çtych po 4 bodech}
        V: SkoreStych:=1; {ka§dì çtych za 1 bod}
      end;
    end;
    
    {CYKLUS PRO VæECHNY HRµ¬E}
    for HracPoradi:= 0 to 3 do begin {kolik tì hr Ÿ hraje}
      Hrac := (HracVynasejici + HracPoradi) mod 4; {kterì hr Ÿ hraje}
      {KartyVynesitelne = karty, kter‚ sm¡ hr Ÿ vyn‚st}
      KartyVynesitelnePocet:=0;
      if Hrac = HracVynasejici then begin {hr Ÿ vyn ç¡}
        if (Hra in [C,B]) AND (RozdaniM[Hrac] * KartyNecerveneM <> []) then begin {plat¡ pravidlo o pýednostn¡m vìnosu neŸervenìch karet a hr Ÿ m  nØjak‚ neŸerven‚ karty => hr Ÿ vyn ç¡ neŸervenou kartu}
          {do pole KartyVynesitelne d  karty, kter‚ lze vyn‚st}
          for j:= 0 to (PocetKaret[Hrac]-1) do begin
            if (Rozdani[Hrac][j] mod 4) <> 0 then pridejDoKartyVynesitelne(Rozdani[Hrac][j]); {nen¡-li karta Ÿerven , m…§e ji hr Ÿ vyn‚st}
          end;
        end else pridejDoKartyVynesitelneVsechny; {vyn ç¡ cokoliv}
      end else begin {hr Ÿ pýihazuje}
        if (RozdaniM[Hrac] * KartyPodleBarevM[StychBarva] <> []) then begin {hr Ÿ ct¡ barvu - m  karty stejn‚ barvy jako je barva çtychu}
        {vyn ç¡ kartu barvy çtychu}
          {do pole KartyVynesitelne d  karty, kter‚ lze vyn‚st}
          for j:= 0 to (PocetKaret[Hrac]-1) do begin
            if (Rozdani[Hrac][j] mod 4) = StychBarva then pridejDoKartyVynesitelne(Rozdani[Hrac][j]);
          end;
        end else pridejDoKartyVynesitelneVsechny; {vyn ç¡ cokoliv}
      end;
      
      {HRµ¬ VYBÖRµ KARTU Z POLE KartyVynesitelne}
      if Hrac=HracClovek then hratManualne else UI;
      
      {BARVA æTYCHU}
      if HracPoradi=0 then StychBarva:=Karta mod 4; {pokud çlo o vìnos, je barva çtychu d na vynesenou kartou}
      
      prihodit; {realizace pýihozen¡ karty}
      
      {VíSTUP}
      vypisZpravu(KartaNesenaHracem);
      
      {StychMaxTyp, StychMaxHrac}
      if (Karta mod 4) = StychBarva then begin {byla ctØna barva}
        if (Karta div 4) > StychMaxTyp then begin {karta pýeb¡j¡ - je nejvyçç¡ dosud vynesen }
          StychMaxTyp := Karta div 4;
          StychMaxHrac:= Hrac;
        end;
      end;
      
      {SKàRE pokud Karta je trestn }
      if Hra in [C,F,B] then begin {jedn  se o trestnou kartu?}
        case Hra of
          C: if (Karta mod 4) = 0 then inc(SkoreStych  ); {karta je Ÿerven  -> 1 bod}
          F: if (Karta div 4) = 5 then inc(SkoreStych,2); {karta je filek -> 2 body}
          B: if  Karta        =24 then inc(SkoreStych,8); {karta je bedrn¡k -> 8 bod…}
        end;
      end;
    
    end;
    {KONEC - CYKLUS PRO VæECHNY HRµ¬E}
    
    {HRµ¬ StychMaxHrac (ten, kterì bere çtych)}
    inc(SkoreHra[StychMaxHrac],SkoreStych); {z¡sk v  trestn‚ body za çtych}
    if (StychMaxHrac=HracClovek) AND (PocetKaret[Hrac]>0) then pridejDoPaklu(4);  {hr Ÿ je ŸlovØk -> m  pakl; pokud u§ hr Ÿ nem  karty, nen¡ týeba prov dØt; nesen‚ karty byly 4}
        
    {trestnì bod maturanta?}
    if (Maturita <> 0) AND (SkoreHra[Talie]>0) then begin {hr la se maturita a maturant dostal bod; maturuj¡c¡ hr Ÿ = Ÿ¡slo Talie}
      vypisZpravu(MaturantNeodmaturoval);
      {vçichni maj¡ 0 bod…, maturant m  8 bod…}
      nulujPole(SkoreHra);
      SkoreHra[Talie] := 8;
      break;
    end;
    
    {bedrn¡k?}
    if (Hra = B) AND (SkoreStych>0) then begin {hr l se bedrn¡k a byl odhozen}
      vypisZpravu(Bedrnik);
      break;
    end;
    
    {ZAKON¬ENÖ}
    HracVynasejici:=StychMaxHrac;
    vypisZpravu(KonecStychu);
  end; {KONEC - CYKLUS PRO KA¦Dí VíNOS}
end; {KONEC - procedure hratPrebijeci}

procedure hratQarty;
var j: byte;
label Vitezstvi;
begin
  {CYKLUS PRO KA¦Dí VíNOS}
  while (PocetKaret[0] <> 0) AND (PocetKaret[1] <> 0) AND (PocetKaret[2] <> 0) AND (PocetKaret[3] <> 0) do begin  {dokud maj¡ vçichni hr Ÿ¡ karty}
    {INICIALIZACE VíNOSU}
    cekejNaStisk;
    clrscr;
    vypisZpravu(InformaceNaZacatkuStychuQ);
    StychMaxHrac:=HracVynasejici; {nejvyçç¡ kartu nejdý¡v urŸitØ vynese prvn¡ hr Ÿ}
    HracPoradi := 0;
    Hrac := HracVynasejici; {kterì hr Ÿ hraje}
    {KartyVynesitelne = karty, kter‚ sm¡ hr Ÿ vyn‚st}
    KartyVynesitelnePocet:=0;
    if (Hrac=Talie) AND (PocetKaret[Hrac]=8) then begin {jde o prvn¡ vìnos}
      if (RozdaniM[Hrac] - KartyDivokaKartaM = []) then begin {hr Ÿ m  divokou kartu - jen F, K a E}
        if (RozdaniM[Hrac] * KartyFilkyM = []) then begin {hr Ÿ m  kr lovskou kvartu => zv¡tØz¡, vyn ç¡ libovoln‚ho kr le}
          for j:= 0 to (PocetKaret[Hrac]-1) do begin
            if (Rozdani[Hrac][j] div 4) = 6 then pridejDoKartyVynesitelne(Rozdani[Hrac][j]) {karta je kr l - hr Ÿ ji m…§e vyn‚st}
          end;
        end else begin {hr Ÿ m  divokou kartu => vyn ç¡ libovoln‚ho filka}
          for j:= 0 to (PocetKaret[Hrac]-1) do begin
            if (Rozdani[Hrac][j] div 4) = 5 then pridejDoKartyVynesitelne(Rozdani[Hrac][j]) {karta je filek, hr Ÿ ji m…§e vyn‚st}
          end;
        end;
      end else begin {hr Ÿ nem  divokou kartu => vyn ç¡ cokoliv menç¡ho ne§ filka}
        for j:= 0 to (PocetKaret[Hrac]-1) do begin
          if Rozdani[Hrac][j] < 20 then pridejDoKartyVynesitelne(Rozdani[Hrac][j]) {karta je menç¡ ne§ filek, hr Ÿ ji m…§e vyn‚st}
        end;
      end
    end else begin {nejde o prvn¡ vìnos, vyn ç¡ cokoliv}
      if PocetKaret[Hrac] = 1 then begin  {vyn çej¡c¡mu hr Ÿi zbyla posledn¡ karta -> na tu se "kouk " (nepýikl d  se na ni) a hr Ÿ v¡tØz¡}
        Karta:=Rozdani[Hrac][0];
        PocetKaret[Hrac]:=0;
        vypisZpravu(KartaNesenaHracem);
        vypisZpravu(NaTuhleSeKouka);
        goto Vitezstvi; {jde o urŸitou nestandardn¡ situaci, proto je pou§it skok}
      end else pridejDoKartyVynesitelneVsechny; {m…§e zahr t libovolnou kartu}
    end;
      
    {HRµ¬ VYBÖRµ KARTU Z POLE KartyVynesitelne}
    if Hrac=HracClovek then hratManualne else UI;
    
    prihodit; {realizace pýihozen¡ karty}
    
    {VíSTUP}
    vypisZpravu(KartaNesenaHracem);

    {CYKLUS PRO ZBíVAJÖCÖ KARTY}
    j:=0; {indikace breaku}
    for HracPoradi := 1 to 3 do begin
      inc(Karta,4);
      if (Karta > 31) OR NOT (Karta in (RozdaniM[0]+RozdaniM[1]+RozdaniM[2]+RozdaniM[3])) then begin j:=1; break; end; {dalç¡ karta by byla vyçç¡ ne§ E, nebo ji nikdo u§ nem }
      for Hrac := 0 to 3 do begin   {zjiçœujeme, kterì hr Ÿ m  Kartu}
        if (Karta in RozdaniM[Hrac]) then begin {m  ji}
          prihodit;
          StychMaxHrac:=Hrac;   {hr Ÿ vynesl souŸasnou nejvyçç¡ kartu ve çtychu}
          vypisZpravu(KartaNesenaHracem);
        end;
      end;
    end;
    if j=1 then dec(HracPoradi); {byl break, posledn¡m hraj¡c¡m hr Ÿem byl tedy HracPoradi-1}
    
    {HRµ¬ StychMaxHrac (ten, kterì bere çtych)}
    if StychMaxHrac=HracClovek then pridejDoPaklu(HracPoradi+1);  {hr Ÿ je ŸlovØk -> m  pakl; neseno bylo HracPoradi+1 karet}
        
    {ZAKON¬ENÖ}
    HracVynasejici:=StychMaxHrac;
    vypisZpravu(KonecStychuQ);
  end; {KONEC - CYKLUS PRO KA¦Dí VíNOS}
  Vitezstvi:
  for Hrac:= 0 to 3 do begin
    SkoreHra[Hrac]:=PocetKaret[Hrac];
    if SkoreHra[Hrac]=0 then vypisZpravu(VitezstviQ);
  end;
  
  {trestnì bod maturanta?}
  if (Maturita <> 0) AND (SkoreHra[Talie]>0) then begin {hr la se maturita a maturant dostal bod; maturuj¡c¡ hr Ÿ = Ÿ¡slo Talie}
    vypisZpravu(MaturantNeodmaturoval);
    {vçichni maj¡ 0 bod…, maturant m  8 bod…}
    nulujPole(SkoreHra);
    SkoreHra[Talie] := 8;
  end;
  
end;

procedure hratDesitky;
var j: byte;
begin
  {INICIALIZACE HRY}
  Hrac:=HracVynasejici;
  HracPoradi:=0;
  cekejNaStisk;
  clrscr;
  vypisZpravu(InformaceNaZacatkuHryD);
  {CYKLUS PRO KA¦Dí VíNOS}
  while (PocetKaret[0] <> 0) AND (PocetKaret[1] <> 0) AND (PocetKaret[2] <> 0) AND (PocetKaret[3] <> 0) do begin  {dokud maj¡ vçichni hr Ÿ¡ karty}
    
    Vynos:=0; {kolik karet ji§ hr Ÿ vylo§il}
    
    repeat  {v des¡tk ch m…§e hr Ÿ vyn çet karty, dokud m…§e}
      {KartyVynesitelne = karty, kter‚ sm¡ hr Ÿ vyn‚st}
      KartyVynesitelnePocet:=0;
      for j:= 0 to (PocetKaret[Hrac]-1) do begin
        if (Rozdani[Hrac][j] div 4 = 3) OR (predchoziD(Rozdani[Hrac][j]) in KartyZahraneM) then pridejDoKartyVynesitelne(Rozdani[Hrac][j]) {karta je des¡tka nebo pýedchoz¡ karta je na stole}
      end;
      {vyn‚st kartu}
      if KartyVynesitelnePocet=0 then begin
        {nem…§e vyn‚st}
        Karta:=32;
        if Vynos=0 then begin {œuk}
          vypisZpravu(TukD);
          inc(SkoreHra[Hrac]);
          if Hrac=HracClovek then cekejNaStisk;
        end;
      end else begin
        {HRµ¬ VYBÖRµ KARTU Z POLE KartyVynesitelne}
        if Hrac=HracClovek then hratManualne else UI;
        if Karta<>32 then begin
          {PüIHOZENÖ}
          prihodit;
          vypisZpravu(KartaNesenaHracemD);
        end else begin
          {nepýihozen¡}
          if Vynos=0 then begin {œuk}
            vypisZpravu(TukD);
            inc(SkoreHra[Hrac]);
          end;
        end;
      end;
      inc(Vynos);
    until (Karta=32) OR (PocetKaret[Hrac]=0);
    
    {ZAKON¬ENÖ}
    if PocetKaret[Hrac]=0 then break;  {t¡m se dostaneme z cyklu ven => k v¡tØzstv¡}
    Hrac:= (Hrac+1) mod 4; {n sleduj¡c¡ hr Ÿ}
    HracPoradi:= (HracPoradi+1) mod 4; {n sleduj¡c¡ hr Ÿ}
    
    {trestnì bod maturanta?}
    if (Maturita <> 0) AND (SkoreHra[Talie]>0) then break; {hr la se maturita a maturant dostal bod; maturuj¡c¡ hr Ÿ = Ÿ¡slo Talie}
  
  end; {KONEC - CYKLUS PRO KA¦Dí VíNOS}
  
  vypisZpravu(VitezstviD);
  
  for Hrac:= 0 to 3 do begin
    inc(SkoreHra[Hrac],PocetKaret[Hrac]);
  end;
  
  {trestnì bod maturanta?}
  if (Maturita <> 0) AND (SkoreHra[Talie]>0) then begin {hr la se maturita a maturant dostal bod; maturuj¡c¡ hr Ÿ = Ÿ¡slo Talie}
    vypisZpravu(MaturantNeodmaturoval);
    {vçichni maj¡ 0 bod…, maturant m  8 bod…}
    nulujPole(SkoreHra);
    SkoreHra[Talie] := 8;
  end;
  
end;

{########################
ZA¬µTEK HLAVNÖHO PROGRAMU
########################}
begin
  
  {inicializace}
  randomize;
  TextColor(BarvyPrg[0]);
  TextBackground(BarvyPrg[1]);
  TextMode(C80);
  clrscr;
  assign(log,'lora.log');
  rewrite(log);
  
  for Karta := 0 to 31 do Balicek[Karta]:=Karta; {karty v bal¡Ÿku v poýad¡ dan‚m jejich Ÿ¡sly}
  nulujPole(SkoreCelkove);
  nulujPole(CistaStovka);
  
  HracClovek:=random(4);  {Ÿ¡slo hr Ÿe, kterì je ŸlovØk}
  vypisZpravu(HrajeteJako);
  
  {HLAVNÖ CYKLUS}
  for Talie:= 0 to 3 do begin
    {inicializace t lie}
    Maturita:=0; {nehraje se maturita}
    Hra:= C;   {poŸ teŸn¡ hra !}
    while true do begin {cyklus pro ka§dou d¡lŸ¡ hru v t lii Talie - p…vodnØ to byl for-cyklus s iteraŸn¡ promØnnou Hra, ale pak bylo nutn‚ mØnit hodnotu iteraŸn¡ promØnn‚, co§ se nel¡b¡ FPC}
      {inicializace hry}
      zamichat;
      rozdat;
      HracVynasejici:=Talie; {v 1. t lii vyn ç¡ v ka§d‚ hýe jako prvn¡ 1. hr Ÿ, ve 2. t lii 2. hr Ÿ... (BéNO)}
      nulujPole(SkoreHra);
      for Hrac := 0 to 3 do PocetKaret[Hrac] := 8; {hr Ÿ m  8 karet}
      Pakl[0]:=32; {pr zdnì pakl - zar §ka na zaŸ tek}
      KartyZahraneM := []; {nebyly dosud zahr ny § dn‚ karty}
      {Ÿist  stovka}
      if (Hra=B) AND (Talie=2) then begin
        {ŸlovØk vol¡, zda se bude pokouçet o Ÿistou stovku}
        if ZIVYHRAC=1 then begin
          cekejNaStisk;
          vypisZpravu(Cista100);
          CistaStovka[HracClovek] := readNumberChar(0,1);
          vypisZpravu(Cista100Info);
        end else CistaStovka[HracClovek] := 0;
      end;
      {maturita}
      if Hra = M then begin  {maturant vyb¡r  hru}
        inc(Maturita);
        if Talie=HracClovek then vyberHru else Hra:=B;  {ŸlovØk vyb¡r  hru k maturitØ; poŸ¡taŸ v§dy vyb¡r  Bedrn¡ka}
      end;
      {HRµT}
      case Hra of
        C..B: hratPrebijeci;  {bude se hr t nØjak  pýeb¡jec¡ hra - C, F, P, V, B}
        Q: hratQarty;         {bude se hr t Q}
        D: hratDesitky;       {bude se hr t D}
      end;
      {ukonŸen¡, nastaven¡ n sleduj¡c¡ hry}
      skorePrepocti;
      vypisZpravu(InfoSkore);
      {!break;}
      if (Maturita <> 0) then begin {hr la se maturita; maturuj¡c¡ hr Ÿ = Ÿ¡slo Talie}
        if (SkoreHra[Talie]=0) OR (Maturita = 3) then break {hr Ÿ odmaturoval nebo u§ to byl týet¡ pokus => konec t lie}
        else Hra:=M; {hr Ÿ m  dalç¡ pokus}
      end else begin
        Hra:=Succ(Hra); {nehr la se maturita => norm lnØ se pokraŸuje n sleduj¡c¡ hrou}
      end;
    end;
  end;
  
  vypisZpravu(KonecLory);
  Close(log);
end.

