
/*********************************************************************
*   < _CARDS.CPP >
**********************************************************************
*   カードの操作関係
**********************************************************************
*                                                   Copyright (C) 2005
*   Programed by Ochi
*********************************************************************/

#include "_speed.h"

CCards::CCards()
{
}

/*********************************************************************
*   数値のカードデータを文字列に変換する
**********************************************************************
*   引数：カードデータ(int)
*   戻り値：カードデータ(char*)
*********************************************************************/
char* CCards::Decode( int nCard )
{
    switch( nCard )
    {
    case NULL:
        return "NL";
        break;
    case 1:
        return "J1";
        break;
    case 2:
        return "S1";
        break;
    case 3:
        return "S2";
        break;
    case 4:
        return "S3";
        break;
    case 5:
        return "S4";
        break;
    case 6:
        return "S5";
        break;
    case 7:
        return "S6";
        break;
    case 8:
        return "S7";
        break;
    case 9:
        return "S8";
        break;
    case 10:
        return "S9";
        break;
    case 11:
        return "SA";
        break;
    case 12:
        return "SB";
        break;
    case 13:
        return "SC";
        break;
    case 14:
        return "SD";
        break;
    case 15:
        return "C1";
        break;
    case 16:
        return "C2";
        break;
    case 17:
        return "C3";
        break;
    case 18:
        return "C4";
        break;
    case 19:
        return "C5";
        break;
    case 20:
        return "C6";
        break;
    case 21:
        return "C7";
        break;
    case 22:
        return "C8";
        break;
    case 23:
        return "C9";
        break;
    case 24:
        return "CA";
        break;
    case 25:
        return "CB";
        break;
    case 26:
        return "CC";
        break;
    case 27:
        return "CD";
        break;
    case 28:
        return "J2";
        break;
    case 29:
        return "H1";
        break;
    case 30:
        return "H2";
        break;
    case 31:
        return "H3";
        break;
    case 32:
        return "H4";
        break;
    case 33:
        return "H5";
        break;
    case 34:
        return "H6";
        break;
    case 35:
        return "H7";
        break;
    case 36:
        return "H8";
        break;
    case 37:
        return "H9";
        break;
    case 38:
        return "HA";
        break;
    case 39:
        return "HB";
        break;
    case 40:
        return "HC";
        break;
    case 41:
        return "HD";
        break;
    case 42:
        return "D1";
        break;
    case 43:
        return "D2";
        break;
    case 44:
        return "D3";
        break;
    case 45:
        return "D4";
        break;
    case 46:
        return "D5";
        break;
    case 47:
        return "D6";
        break;
    case 48:
        return "D7";
        break;
    case 49:
        return "D8";
        break;
    case 50:
        return "D9";
        break;
    case 51:
        return "DA";
        break;
    case 52:
        return "DB";
        break;
    case 53:
        return "DC";
        break;
    case 54:
        return "DD";
        break;
    }
    
    return "ER";
}

/*********************************************************************
*   文字列のカードデータを数値に変換する
**********************************************************************
*   引数：カードデータ(char*)
*   戻り値：カードデータ(int)
*********************************************************************/
int CCards::Encode( char* pszCard )
{
    if (strcmp(pszCard,"NL")== 0)
        return NULL;
    else if (strcmp(pszCard,"J1")== 0)
        return 1;
    else if (strcmp(pszCard,"S1")== 0)
        return 2;
    else if (strcmp(pszCard,"S2")== 0)
        return 3;
    else if (strcmp(pszCard,"S3")== 0)
        return 4;
    else if (strcmp(pszCard,"S4")== 0)
        return 5;
    else if (strcmp(pszCard,"S5")== 0)
        return 6;
    else if (strcmp(pszCard,"S6")== 0)
        return 7;
    else if (strcmp(pszCard,"S7")== 0)
        return 8;
    else if (strcmp(pszCard,"S8")== 0)
        return 9;
    else if (strcmp(pszCard,"S9")== 0)
        return 10;
    else if (strcmp(pszCard,"SA")== 0)
        return 11;
    else if (strcmp(pszCard,"SB")== 0)
        return 12;
    else if (strcmp(pszCard,"SC")== 0)
        return 13;
    else if (strcmp(pszCard,"SD")== 0)
        return 14;
    else if (strcmp(pszCard,"C1")== 0)
        return 15;
    else if (strcmp(pszCard,"C2")== 0)
        return 16;
    else if (strcmp(pszCard,"C3")== 0)
        return 17;
    else if (strcmp(pszCard,"C4")== 0)
        return 18;
    else if (strcmp(pszCard,"C5")== 0)
        return 19;
    else if (strcmp(pszCard,"C6")== 0)
        return 20;
    else if (strcmp(pszCard,"C7")== 0)
        return 21;
    else if (strcmp(pszCard,"C8")== 0)
        return 22;
    else if (strcmp(pszCard,"C9")== 0)
        return 23;
    else if (strcmp(pszCard,"CA")== 0)
        return 24;
    else if (strcmp(pszCard,"CB")== 0)
        return 25;
    else if (strcmp(pszCard,"CC")== 0)
        return 26;
    else if (strcmp(pszCard,"CD")== 0)
        return 27;
    else if (strcmp(pszCard,"J2")== 0)
        return 28;
    else if (strcmp(pszCard,"H1")== 0)
        return 29;
    else if (strcmp(pszCard,"H2")== 0)
        return 30;
    else if (strcmp(pszCard,"H3")== 0)
        return 31;
    else if (strcmp(pszCard,"H4")== 0)
        return 32;
    else if (strcmp(pszCard,"H5")== 0)
        return 33;
    else if (strcmp(pszCard,"H6")== 0)
        return 34;
    else if (strcmp(pszCard,"H7")== 0)
        return 35;
    else if (strcmp(pszCard,"H8")== 0)
        return 36;
    else if (strcmp(pszCard,"H9")== 0)
        return 37;
    else if (strcmp(pszCard,"HA")== 0)
        return 38;
    else if (strcmp(pszCard,"HB")== 0)
        return 39;
    else if (strcmp(pszCard,"HC")== 0)
        return 40;
    else if (strcmp(pszCard,"HD")== 0)
        return 41;
    else if (strcmp(pszCard,"D1")== 0)
        return 42;
    else if (strcmp(pszCard,"D2")== 0)
        return 43;
    else if (strcmp(pszCard,"D3")== 0)
        return 44;
    else if (strcmp(pszCard,"D4")== 0)
        return 45;
    else if (strcmp(pszCard,"D5")== 0)
        return 46;
    else if (strcmp(pszCard,"D6")== 0)
        return 47;
    else if (strcmp(pszCard,"D7")== 0)
        return 48;
    else if (strcmp(pszCard,"D8")== 0)
        return 49;
    else if (strcmp(pszCard,"D9")== 0)
        return 50;
    else if (strcmp(pszCard,"DA")== 0)
        return 51;
    else if (strcmp(pszCard,"DB")== 0)
        return 52;
    else if (strcmp(pszCard,"DC")== 0)
        return 53;
    else if (strcmp(pszCard,"DD")== 0)
        return 54;
    else
        return 0;
}

/*********************************************************************
*   カードデータをバッファからコピーする
**********************************************************************
*   引数：無し
*   戻り値：完了(bool)
*********************************************************************/
bool CCards::ExtraSet( void )
{
    int nCount;

    nBa[0]=nBaBuf[0];
    nBa[1]=nBaBuf[1];

    for( nCount=0; nCount<8; nCount++ )
    {
        nTefuda[0][nCount] = nTefudaBuf[0][nCount];
    }
    for( nCount=0; nCount<8; nCount++ )
    {
        nTefuda[1][nCount] = nTefudaBuf[1][nCount];
    }

    for( nCount=0; nCount<32; nCount++ )
    {
        nYama[0][nCount] = nYamaBuf[0][nCount];
    }
    for( nCount=0; nCount<32; nCount++ )
    {
        nYama[1][nCount] = nYamaBuf[1][nCount];
    }

    return true;
}

/*********************************************************************
*   バッファのカードデータを見たいときに使う
**********************************************************************
*   引数：場、手札、山(int*)
*   戻り値：終了(bool)
*********************************************************************/
bool CCards::ExtraSetToBuf( int* ptrBa, int* ptrTefuda, int* ptrYama )
{
    int nCount;

    nBaBuf[0] = *(ptrBa);
    nBaBuf[1] = *(ptrBa+1);

    for( nCount=0; nCount<16; nCount++ )
    {
        if ( nCount<8 )
        {
            nTefudaBuf[0][nCount] = *(ptrTefuda+nCount);
        }
        else
        {
            nTefudaBuf[1][nCount-8] = *(ptrTefuda+nCount);
        }
    }

    for( nCount=0; nCount<64; nCount++ )
    {
        if( nCount<32 )
        {
            nYamaBuf[0][nCount] = *(ptrYama+nCount);
        }
        else
        {
            nYamaBuf[1][nCount-32] = *(ptrYama+nCount);
        }
    }

    return true;
}

/*********************************************************************
*   ２つのカードが、数字が１違う関係かどうかを判断する
**********************************************************************
*   引数：２枚のカード(int)
*   戻り値：その関係である-true その関係でない-false(bool)
*********************************************************************/
bool CCards::Judgment( int nCardA, int nCardB )
{
    char* pszCardA;
    char* pszCardB;

    pszCardA = Decode( nCardA );
    pszCardB = Decode( nCardB );
    // ジョーカーなら無条件で成功
    if( pszCardA[0] == 'J' || pszCardB[0] == 'J' )
    {
        return true;
    }

    if( pszCardA[1]=='2' || pszCardA[1]=='3' ||
        pszCardA[1]=='4' || pszCardA[1]=='5' ||
        pszCardA[1]=='6' || pszCardA[1]=='7' ||
        pszCardA[1]=='8' )
    {
        // カードの数字が±１ならば成功
        if ( pszCardA[1]-1==pszCardB[1] || pszCardA[1]+1==pszCardB[1] )
        {
            return true;
        }
    }
    else if( pszCardA[1]=='1' )
    {
        if ( pszCardB[1]=='D' || pszCardB[1]=='2' )
        {
            return true;
        }
    }
    else if ( pszCardA[1]=='9' )
    {
        if( pszCardB[1]=='8' || pszCardB[1]=='A' )
        {
            return true;
        }
    }
    else if( pszCardA[1]=='A' )
    {
        if( pszCardB[1]=='9' || pszCardB[1]=='B' )
        {
            return true;
        }
    }
    else if( pszCardA[1] == 'B' )
    {
        if( pszCardB[1]=='A' || pszCardB[1]=='C' )
        {
            return true;
        }
    }
    else if( pszCardA[1]=='C' )
    {
        if( pszCardB[1]=='B' || pszCardB[1]=='D' )
        {
            return true;
        }
    }
    else if( pszCardA[1]=='D' )
    {
        if( pszCardB[1]=='C' || pszCardB[1]=='1' )
        {
            return true;
        }
    }   

    return false;
}

/*********************************************************************
*   ゲームが終了しているのか否かを判定する
**********************************************************************
*   引数　：無し
*   戻り値：終了している-true 終了していない-false(bool)
*********************************************************************/
bool CCards::JudgmentStop( void )
{
    int i, n;

    for( i=0; i<2; i++ )
    {
        for( n=0; n<4; n++ )
        {
            if( nYama[i][0]!=NULL || nTefuda[i][n]!=NULL )
            {
                goto OK;
            }
            if( i==1 && n==3 )
            {
                return false;
            }
        }
    }
OK:
    for( i=0; i<2; i++ )
    {
        for( n=0; n<4; n++ )
        {
            if( nTefuda[i][n] != NULL )
            {
                if ( Judgment(nTefuda[i][n],nBa[0])==true ||
                     Judgment(nTefuda[i][n],nBa[1])==true )
                {
                    return false;
                }
            }
            else
            {
                if ( nYama[i][0]!=NULL )
                {
                    return false;
                }
            }
        }
    }

    return true;
}

/*********************************************************************
*   プライベートになっているカード情報を渡す
**********************************************************************
*   引数　：カードをセットするポインタ
*   戻り値：終了(bool)
*********************************************************************/
bool CCards::SetBa( int* ptrBa )
{
    *(ptrBa) = nBa[0];
    *(ptrBa+1) = nBa[1];

    return true;
}

bool CCards::SetTefuda( int* ptrTefuda )
{
    int nCount;

    for( nCount=0; nCount<16; nCount++ )
    {
        if( nCount<8 )
        {
            *(ptrTefuda+nCount) = nTefuda[0][nCount];
        }
        else {
            *(ptrTefuda+nCount) = nTefuda[1][nCount-8];
        }
    }

    return true;
}

bool CCards::SetYama( int* ptrYama )
{
    int nCount;

    for( nCount=0; nCount<64; nCount++ )
    {
        if ( nCount<32 )
        {
            *(ptrYama+nCount) = nYama[0][nCount];
        }
        else
        {
            *(ptrYama+nCount) = nYama[1][nCount-32];
        }
    }

    return true;
}

bool CCards::SetBaBuf( int* ptrBa )
{
    *(ptrBa) = nBaBuf[0];
    *(ptrBa+1) = nBaBuf[1];

    return true;
}

bool CCards::SetTefudaBuf( int* ptrTefuda )
{
    int nCount;

    for( nCount=0; nCount<16; nCount++ )
    {
        if( nCount<8 )
        {
            *(ptrTefuda+nCount) = nTefudaBuf[0][nCount];
        }
        else {
            *(ptrTefuda+nCount) = nTefudaBuf[1][nCount-8];
        }
    }

    return true;
}

bool CCards::SetYamaBuf( int* ptrYama )
{
    int nCount;

    for( nCount=0; nCount<64; nCount++ )
    {
        if ( nCount<32 )
        {
            *(ptrYama+nCount) = nYamaBuf[0][nCount];
        }
        else
        {
            *(ptrYama+nCount) = nYamaBuf[1][nCount-32];
        }
    }

    return true;
}

/*********************************************************************
*   新規にカードを配る
**********************************************************************
*   引数　：無し
*   戻り値：無し
*********************************************************************/
void CCards::SetupCards( void )
{
    int nCards[54];
    
    for( int n=0; n<54; n++ )
    {
        nCards[n] = Random(27)+1;
        if( n>=27 )
        {
            nCards[n] += 27;
        }
        for( int n2=0; n2<n; n2++ ) {
            if( nCards[n]==nCards[n2] ){
                n--;
            }
        }
    }

    for( n=0; n<54; n++ )
    {
        if( n<22 )
            nYama[0][n] = nCards[n];
        else if( n<26 )
            nTefuda[0][n-22] = nCards[n];
        else if( n<27 )
            nBa[0] = nCards[n];
        else if( n<49 )
            nYama[1][n-27] = nCards[n];
        else if( n<53 )
            nTefuda[1][n-49] = nCards[n];
        else if( n==53 )
            nBa[1] = nCards[n];
    }
}

/*********************************************************************
*   山から場に１枚カードを出す　山に無い場合は手札から出す
**********************************************************************
*   引数　：無し
*   戻り値：終了(bool)
*********************************************************************/
bool CCards::SetRestart( void )
{
    int n;
    if( nYama[0][0]!=NULL )
    {
        // 取ってずらす
        nBa[0] = nYama[0][0];
        for( n=0; n<23; n++ )
        {
            nYama[0][n] = nYama[0][n+1];
            if( nYama[0][n+1]==NULL )
            {
                break;
            }
        }
    }
    else
    {
        for( n=0; n<4; n++ )
        {
            if( nTefuda[0][n]!=NULL )
            {
                nBa[0] = nTefuda[0][n];
                nTefuda[0][n] = NULL;
                break;
            }
            if( n==3 )
            {
                return false;
            }
        }
    }

    return true;
}

/*********************************************************************
*   カードを起動時の状態にする
**********************************************************************
*   引数　：無し
*   戻り値：無し
*********************************************************************/
void CCards::SetupDemo ( void )
{
    nYama[0][0]   = Encode( "S2" );
    nYama[1][0]   = Encode( "S3" );
    nTefuda[0][0] = Encode( "NL" );
    nTefuda[0][1] = Encode( "NL" );
    nTefuda[0][2] = Encode( "NL" );
    nTefuda[0][3] = Encode( "NL" );
    nTefuda[1][0] = Encode( "NL" );
    nTefuda[1][1] = Encode( "NL" );
    nTefuda[1][2] = Encode( "NL" );
    nTefuda[1][3] = Encode( "NL" );
    nBa[0]        = Encode( "J1" );
    nBa[1]        = Encode( "J2" );
}

/*********************************************************************
*   カードデータを受け取ったメッセージの通りに更新する
*   自分で出したメッセージなら、そのまま更新し
*   相手から送られてデータなら、自分と相手のカードを反対にする
**********************************************************************
*   引数　：受信したメッセージ(char*), カードを反対にするか否か(int)
*   戻り値：カードデータ(char*)
*********************************************************************/
int CCards::Update( char* szBuf, int nConverse )
{
    int     n;
    int     n2;
    int     count;
    int     card_no;
    char    szCard[4];

    n=0;
    n2=0;
    while( n2<4 )
    {
        if( szBuf[n]==' ' )
        {
            n2++;
        }
        n++;
    }
    count = 0;
    card_no = 0;

    while( 1 )
    {
        if( szBuf[n]=='\0' || szBuf[n]==NULL )
        {
            break;
        }
        else if(szBuf[n]==' ')
        {
            n++;
            count++;
            card_no = 0;
            continue;
        }
        else
        {
            szCard[0] = szBuf[n];
            szCard[1] = szBuf[n+1];
            szCard[2] = '\0';
            n+=2;
        }
        if( nConverse==1 )
        {
            switch ( count )
            {
            case 0:
                nYama[1][card_no]=Encode( szCard );
                break;
            case 1:
                nYama[0][card_no]=Encode( szCard );
                break;
            case 2:
                nTefuda[1][card_no]=Encode( szCard );
                break;
            case 3:
                nTefuda[0][card_no]=Encode( szCard );
                break;
            case 4:
                if( card_no==0 )
                {
                    nBa[card_no+1]=Encode( szCard );
                }
                if( card_no==1 )
                {
                    nBa[card_no-2]=Encode( szCard );
                }
                break;
            }
        }
        else
        {
            switch ( count )
            {
            case 0:
                nYama[0][card_no]=Encode( szCard );
                break;
            case 1:
                nYama[1][card_no]=Encode( szCard );
                break;
            case 2:
                nTefuda[0][card_no]=Encode( szCard );
                break;
            case 3:
                nTefuda[1][card_no]=Encode( szCard );
                break;
            case 4:
                nBa[card_no]=Encode( szCard );
                break;
            }
        }
        
        card_no++;
    }

    bool bUser[2];
    
    for( count=0; count<2; count++ )
    {
        for( n=0; n<4; n++ )
        {
            if( nYama[count][0]!=NULL || nTefuda[count][n]!=NULL )
            {
                bUser[count] = false;
                break;
            }
            if( n==3 )
            {
                bUser[count] = true;
            }
        }
    }

    if( bUser[0]==true && bUser[1]== false )
    {
        return WIN;
    }
    else if( bUser[0]==false && bUser[1]==true )
    {
        return DEFEAT;
    }
    else if( bUser[0]==true && bUser[1]==true )
    {
        return DRAW;
    }

    return 0;
}