---
# System prepended metadata

title: Guard_f.cpp
tags: [Current Ver.]

---

# Guard_f.cpp
###### tags: `Current Ver.`
```
#include <iostream>
#include <cstdlib>
#include <string.h>
#include "Guard.h"
using namespace std;
#define initial_heat37 192
#define initial_heat28 128
#define initial_heat19 64

struct Gameinfo{
    short playerSelf = 1, BWind = 1, SWind = 1,
            OpenAt = 1, Master = 1, MCombo = 0;
            
    void SetSelfID(short player_ID){
        playerSelf = player_ID;
    }
    void SetInfo(short BW, short SW, short OP, short GM, short MC){
        BWind = BW;
        SWind = BW;
        OpenAt = OP;
        Master = GM;
        MCombo = MC;
    }

    Gameinfo() {}
};
Gameinfo currentGame;

short Hand[17];         //Hand can contain upmost to 17 tiles
short Hand_size;        //Hand's size
short Table[474];       //all tile's current status <tile , status> (-x = player x's thrown tile, 0 = unknown, x = player x's tile)
short Restsum[48];      //tile's non-thrown count
short Drawtime[48][5];  //players Hand change overtime
short Heat[40];         //numeric tile's possiblity to form a straight
short muscle[40];       //muscle affect source
short tothrow;

short LastThrow = 0; // 最後一個棄牌
short LastPlayer = 0; // 上一個玩家

char command_title[20]; // 指令
char command_contxt[70]; // 指令參數

short Guard(void)
{
    // 開始(input)
    switch (command_title[1]) //first letter from command
    {
    case 's': //start
        currentGame.SetSelfID((short)command_contxt[3] - '0');
        break;

    // 本局資訊(input)
    case 'i': //init
    {
        if (CmdCompare("/initGame"))
        {
            char BWind[6] = {0};
            char SWind[6] = {0};
            SubContxt(BWind, command_contxt, 0, ' ');
            SubContxt(SWind, command_contxt, 0, ' ');
            short OpenAt, Master, MCombo;
            OpenAt = (short)command_contxt[0] - '0';
            Master = (short)command_contxt[2] - '0';
            MCombo = (short)command_contxt[4] - '0';


            currentGame.SetInfo(CheckWind(BWind), CheckWind(SWind), OpenAt, Master, MCombo); //set game info
            GameReset(); //reset variables
        }

        // 發牌(input)
        else if (CmdCompare("/initCard"))
        {
            char subtxt[4] = {0};
            short tile_ini[17] = {0};
            //if莊家 17張手牌, else 16張手牌
            if(currentGame.playerSelf == currentGame.Master)
                Hand_size = 17;
            else
                Hand_size = 16;
            for(short i = 0; i < Hand_size; i++)
            {
                SubContxt(subtxt, command_contxt, 0, ' ');
                tile_ini[i] = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');
            }


            SetHand(tile_ini); //set hand tiles
        }
        break;
    }

    // 摸(input)
    case 'm': //mo
    {
        short tile_mo = (command_contxt[0] - '0') * 100 + (command_contxt[1] - '0') * 10 + (command_contxt[2] - '0');


        addHand(tile_mo); //add tile to hand
        break;
    }

    // 詢問AI動作(input)
    case 'a': //ask
    {
        // throw丟(output)
        if (command_contxt[0] == 't')
        {
            Guard_AskThrow();
        }

        // eat吃(output)
        else if (command_contxt[0] == 'e')
        {
            cout << "/pass" << endl;
        }

        // pong碰(output)
        else if (command_contxt[0] == 'p')
        {
            cout << "/pass" << endl;
        }

        // gong槓(output)
        else if (command_contxt[0] == 'g')
        {
            cout << "/pass" << endl;
        }

        // hu胡(output)
        else if (command_contxt[0] == 'h')
        {
            cout << "/hu" << endl;
        }
        break;
    }

    //棄牌(input)
    case 't': //throw
    {
        short player_ID = command_contxt[0] - '0';
        short tile = (command_contxt[2] - '0') * 100 + (command_contxt[3] - '0') * 10 + (command_contxt[4] - '0');

        Guard_Throw(player_ID, tile);

        break;
    }

    // 吃
    case 'e':
    {
        /*char subtxt[3] = {0};
        SubContxt(subtxt, command_contxt, 0, ' ');

        short player_ID = subtxt[0] - '0';
        short tile;
        for (short i = 0; i < 3; i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');
            
            if (player_ID == currentGame.playerSelf)
            {
                RemoveHand(tile);
            }
            if(tile == LastThrow) continue;

            Table[tile] = player_ID;

            if (GetType(tile) != 4)
                HeatProcess(tile);

            Restsum[RemoveID(tile)]--;
        }

        // drawtime 0
        DrawTimeZero(LastThrow, 0);

        LastThrow = 0;
        break;*/
        
        char subtxt[3] = {0};
        SubContxt(subtxt, command_contxt, 0, ' ');

        short player_ID = subtxt[0] - '0';
        short tile[3];

        for (short i = 0; i < 3; i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile[i] = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');
        }

        Guard_Eat(player_ID, tile);
        break;
    }

    // 碰
    case 'p':
    {
        /*char subtxt[3] = {0};
        SubContxt(subtxt, command_contxt, 0, ' ');

        short player_ID = subtxt[0] - '0';
        short tile;
        for (short i = 0; i < 3; i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');

            if (player_ID == currentGame.playerSelf)
                RemoveHand(tile);

            if(tile == LastThrow) continue;
            
            Table[tile] = player_ID;

            if (GetType(tile) != 4)
                HeatProcess(tile);

            Restsum[RemoveID(tile)]--;
        }

        LastThrow = 0;
        break;*/
        char subtxt[3] = {0};
        SubContxt(subtxt, command_contxt, 0, ' ');

        short player_ID = subtxt[0] - '0';
        short tile[3] = {0};
        for (short i = 0; i < 3; i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile[i] = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');

            if(tile[i] == LastThrow) continue;
        }

        Guard_Pong(player_ID, tile);
        break;
    }

    // 槓
    case 'g':
    {
        /*char subtxt[3] = {0};
        short tile;

        SubContxt(subtxt, command_contxt, 0, ' ');
        short player_ID = subtxt[0] - '0';
        SubContxt(subtxt, command_contxt, 0, ' ');
        short Gtype = subtxt[0] - '0';

        // drawtime+
        DrawTimePlus(player_ID);

        for (short i = 0; i < ((Gtype != 1)? 4 : 1); i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');

            if (player_ID == currentGame.playerSelf)
                RemoveHand(tile);

            if (tile == LastThrow || Gtype == 0) continue;//若為暗槓則跳過

            Table[tile] = player_ID;

            if (GetType(tile) != 4)
                HeatProcess(tile);
        }

        LastThrow = 0;
        break;*/
        
        char subtxt[3] = {0};
        short tile_arr[4] = {0};

        SubContxt(subtxt, command_contxt, 0, ' ');
        short player_ID = subtxt[0] - '0';
        SubContxt(subtxt, command_contxt, 0, ' ');
        short Gtype = subtxt[0] - '0';

        for (short i = 0; i < ((Gtype != 1)? 4 : 1); i++)
        {
            SubContxt(subtxt, command_contxt, 0, ' ');
            tile_arr[i] = (subtxt[0] - '0') * 100 + (subtxt[1] - '0') * 10 + (subtxt[2] - '0');
        }

        Guard_Gong(player_ID, tile_arr, Gtype);
        break;
    }

    // 確認AI有連接
    case 'r': //ready
        cout << "/ready" << endl;
        break;

    // 有人胡牌
    case 'h': //hu
        break;

    // 程式結束(input)
    case 'q': //quit
        return 0;

    // Other(input)
    default:
        if (CmdCompare("*/print"))
        {
            cout << endl << "Hand size = " << Hand_size << endl;
            for (short i = 0; i < Hand_size; i++)
            {
                change_output(Hand[i]);
                cout << "  ";
                cout << "剩張: " << Restsum[RemoveID(Hand[i])] << "\t";

                if (GetType(Hand[i]) != 4)
                {
                    cout << "Heat: ";
                    cout.width(4);
                    cout << Heat[RemoveID(Hand[i])];
                }
                cout << endl;
            }
        }
        else if (CmdCompare("*/time"))
        {
            cout << endl << "Hand size = " << Hand_size << endl;
            for (short i = 0; i < Hand_size; i++)
            {
                change_output(Hand[i]);
                cout << "  time: ";
                for (short p = 1; p <= 4; p++)
                    cout << Drawtime[RemoveID(Hand[i])][p] << " ";
                cout << endl;
            }
        }
        else
            cout << "Unknown Command!" << endl;
        break;

    } //end of switch

    return -1;
}

bool CmdCompare(const char* CmdToCmp)
{
    bool flag = true;
    short i;
    for (i = 0; CmdToCmp[i] != 0; i++)
    {
        if(command_title[i] != CmdToCmp[i] || i > 20 || command_title[i] == 0)
        {
            flag = false;
            break;
        }
    }
    return flag;
}
bool StrCompare(char* context, const char* Compare) //compare maximum 20 characters
{
    bool flag = true;
    short i;
    for (i = 0; Compare[i] != 0; i++)
        if(context[i] != Compare[i] || i > 20 || context[i] == 0)
        {
            flag = false;
            break;
        }
    return flag;
}

void SubContxt(char* subArr, char* mainArr, short begin, char target)
{
    short i;
    for (i = begin; *(mainArr + i) != target && *(mainArr + i) != 0; i++)
    {
        //cout << *(mainArr + i);
        *(subArr + i) = *(mainArr + i);
    }
    for (short j = begin; *(mainArr + j) != 0; j++)
    {
        *(mainArr + j) = *(mainArr + j + i + 1);
    }
}

short CheckWind(char* wind)
{
    switch (*wind)
    {
    case 'E':
        return 1;
    case 'S':
        return 2;
    case 'W':
        return 3;
    case 'N':
        return 4;

    default:
        return -1;
    }
}

void GameReset(void)
{
    Hand_size = 0;
    for (short i = 0; i < 23; i++)
        Hand[i] = 0;
    for (short i = 11; i <= 47; i++)
    {
        if (i%10 != 0) // 跳過20 30 40
        {
            Table[i*10 + 0] = 0;
            Table[i*10 + 1] = 0;
            Table[i*10 + 2] = 0;
            Table[i*10 + 3] = 0;
            Restsum[i] = 4;
            Drawtime[i][1] = -1;
            Drawtime[i][2] = -1;
            Drawtime[i][3] = -1;
            Drawtime[i][4] = -1;
        }
    }
    for (short i = 11; i <= 39; i++)
    {
        muscle[i] = 0;
        if (i%10 == 0) // 跳過20 30 40
            continue;
        else if (inRange(3, i % 10, 7)) // 3 ~ 7
        {
            Heat[i] = initial_heat37;
        }
        else if (inRange(2, i % 10, 8)) // 2 或 8
        {
            Heat[i] = initial_heat28;
        }
        else // 1 或 9
        {
            Heat[i] = initial_heat19;
        }
    }
}

void HeatProcess(short tile)
{
    if (GetType(tile) == 4)
        return;

    short m2, m1, z0, p1, p2;
    m2 = RemoveID(tile) - 2;
    m1 = RemoveID(tile) - 1;
    z0 = RemoveID(tile);
    p1 = RemoveID(tile) + 1;
    p2 = RemoveID(tile) + 2;
    if (inRange(3, GetDigit(tile), 7))
    {
        Heat[m2] -= Restsum[m2]*Restsum[m1];
        Heat[m1] -= Restsum[m2]*Restsum[m1] + Restsum[m1]*Restsum[p1];
        Heat[z0] -= Restsum[m2]*Restsum[m1] + Restsum[m1]*Restsum[p1] + Restsum[p1]*Restsum[p2];
        Heat[p1] -= Restsum[m1]*Restsum[p1] + Restsum[p1]*Restsum[p2];
        Heat[p2] -= Restsum[p1]*Restsum[p2];
    }
    else if (GetDigit(tile) == 2) // 2
    {
        Heat[m1] -= Restsum[m1]*Restsum[p1];
        Heat[z0] -= Restsum[m1]*Restsum[p1] + Restsum[p1]*Restsum[p2];
        Heat[p1] -= Restsum[m1]*Restsum[p1] + Restsum[p1]*Restsum[p2];
        Heat[p2] -= Restsum[p1]*Restsum[p2];
    }
    else if (GetDigit(tile) == 8) // 8
    {
        Heat[m2] -= Restsum[m2]*Restsum[m1];
        Heat[m1] -= Restsum[m1]*Restsum[p1] + Restsum[m2]*Restsum[m1];
        Heat[z0] -= Restsum[m1]*Restsum[p1] + Restsum[m2]*Restsum[m1];
        Heat[p1] -= Restsum[m1]*Restsum[p1];
    }
    else if (GetDigit(tile) == 1)// 1
    {
        Heat[z0] -= Restsum[p1]*Restsum[p2];
        Heat[p1] -= Restsum[p1]*Restsum[p2];
        Heat[p2] -= Restsum[p1]*Restsum[p2];
    }
    else if (GetDigit(tile) == 9) // 9
    {
        Heat[z0] -= Restsum[m2]*Restsum[m1];
        Heat[m1] -= Restsum[m2]*Restsum[m1];
        Heat[m2] -= Restsum[m2]*Restsum[m1];
    }
}

void MuscleProcess(short tile, short player_ID)
{
    if (GetType(tile) == 4)
        return;
        
    short m3 = RemoveID(tile) - 3;
    short p3 = RemoveID(tile) + 3;

    if (inRange(1, GetDigit(m3), 9))
        muscle[m3] = tile;
    if (inRange(1, GetDigit(p3), 9))
        muscle[p3] = tile;
    
    // cout << m3 << " muscle: " << muscle[m3] << endl;
    // cout << p3 << " muscle: " << muscle[p3] << endl;
}

short MuscleHeat(short tile, short player_ID)
{
    if (GetType(tile) == 4)
        return 0;

    short m2, m1, z0, p1, p2;
    m2 = RemoveID(tile) - 2;
    m1 = RemoveID(tile) - 1;
    z0 = RemoveID(tile);
    p1 = RemoveID(tile) + 1;
    p2 = RemoveID(tile) + 2;
    short mheat = 0;
    //cout << muscle[z0][player_ID] << " from " << tile << " " << player_ID << endl;
    switch (GetDigit(muscle[z0]))
    {
    case 1:
    case 2:
    case 3:
        mheat += Restsum[m1]*Restsum[z0]*Restsum[p1];
        mheat += Restsum[z0]*Restsum[p1]*Restsum[p2];
        break;
    case 7:
    case 8:
    case 9:
        mheat += Restsum[m2]*Restsum[m1]*Restsum[z0];
        mheat += Restsum[m1]*Restsum[z0]*Restsum[p1];
        break;
    case 4:
        if (GetDigit(tile) == 1) mheat = 0;
        else
        {
            mheat += Restsum[m1]*Restsum[z0]*Restsum[p1];
            mheat += Restsum[z0]*Restsum[p1]*Restsum[p2];
        }
        break;
    case 5:
        mheat = Restsum[m1]*Restsum[z0]*Restsum[p1];
        break;
    case 6:
        if (GetDigit(tile) == 9) mheat = 0;
        else
        {
            mheat += Restsum[m2]*Restsum[m1]*Restsum[z0];
            mheat += Restsum[m1]*Restsum[z0]*Restsum[p1];
        }
        break;
    default:
        //cout << "MHeat Error!" << endl;
        break;
    }
    return mheat;
}

short GetType(short tile)
{
    // 如果title_id > 999, print warning
    /*if(tile > 999)
        cout << "[Warning] - The tile > 999.\n";*/
    // return type
    return tile / 100;
}

short GetDigit(short tile)
{
    // 如果title_id > 999, print warning
    /*if(tile > 999)
        cout << "[Warning] - The tile > 999.\n";*/
    // return digit
    return (tile / 10) % 10;
}

short GetID(short tile)
{
    // 如果title_id > 999, print warning
    /*if(tile > 999)
        cout << "[Warning] - The tile > 999.\n";*/
    // return id
    return tile % 10;
}

short RemoveID(short tile)
{
    return tile / 10;
}

bool inRange(short a, short x ,short b)
{
    if (a <= x && x <= b)
        return true;
    return false;
}

void arrClear(short *Arraytoclear, short Arraysize, short Clearvalue = 0)
{
    for (short i = 0; i < Arraysize; i++)
        Arraytoclear[i] = Clearvalue;
}

void change_output(short title_id)
{
    if(GetType(title_id) == 1)
        cout << GetDigit(title_id) << "w ";
    else if(GetType(title_id) == 2)
        cout << GetDigit(title_id) << "t ";
    else if(GetType(title_id) == 3)
        cout << GetDigit(title_id) << "s ";
    else
        if(GetDigit(title_id) == 1)
            cout << "東";
        else if(GetDigit(title_id) == 2)
            cout << "南";
        else if(GetDigit(title_id) == 3)
            cout << "西";
        else if(GetDigit(title_id) == 4)
            cout << "北";
        else if(GetDigit(title_id) == 5)
            cout << "中";
        else if(GetDigit(title_id) == 6)
            cout << "發";
        else
            cout << "白";
}

void InputMethod()
{
    char inputchar;
    bool is_title = true;
    for (short title_size = 0, contxt_size = 0;
        title_size < 20 && contxt_size < 70;)
    {
        inputchar = cin.get();
        if (inputchar == '\n')
        {
            command_title[title_size] = 0;
            command_contxt[contxt_size] = 0;
            break;
        }
        if (!is_title)
        {
            command_contxt[contxt_size++] = inputchar;
            continue;
        }
        else if (is_title && inputchar == ' ')
        {
            is_title = false;
            continue;
        }
        else
            command_title[title_size++] = inputchar;
    }
}

/*************************************************************************/

void Guard_AskThrow()
{
// cout << "LastThrow = " << LastThrow << endl;
        if (LastThrow != 0) // 上回合沒有吃碰槓(時間處理)
            DrawTimeZero(LastThrow, 0);

        bool throwEnd = false, numeric = false;
        tothrow = 0; //the tile to throw

        short reps[48] = {0}; //replicant count
        short t_max[23];
        arrClear(t_max, short(23), short(-1));
        short t_sum[23];
        arrClear(t_sum, short(23), short(-1));

        //time check
        throwEnd = TimeCheck(t_max, t_sum);

        //replicant count
        for (short i = 0; i < Hand_size; i++)
            reps[RemoveID(Hand[i])]++;
// cout << "current throw1: " << tothrow << endl;

        //check for min unknown sum
        //total sum (4 - restsum + replicants) of symbol = 4
        short minsum = 6;
        if (!throwEnd)
        {
            throwEnd = SumCheck(&minsum, reps);
        }
// cout << "current throw2: " << tothrow << endl;

        // numeric calculation
        if (!throwEnd)
        {
            short heatthrow = HeatCalculation(t_sum);
            if (minsum > Restsum[RemoveID(heatthrow)]) tothrow = heatthrow;
// cout << minsum << " vs " << Restsum[RemoveID(heatthrow)] << endl;
        }
        else throwEnd = true;

        cout << "/throw " << tothrow << endl << flush;
}

void Guard_Throw(short player_ID, short tile)
{
        if (player_ID == currentGame.playerSelf)
        {
            RemoveHand(tile);
// change_output(tile);
// cout << Restsum[RemoveID(tile)] << endl;
        }

        if (LastThrow != 0) // 上回合沒有吃碰槓(時間處理)
        {
            DrawTimeZero(LastThrow, 0);

            // drawtime+
            DrawTimePlus(player_ID);
        }

        DrawTimeZero(tile, player_ID); //棄牌家時間歸零
        LastThrow = tile;

        if (GetType(tile) != 4)
        {
            HeatProcess(tile);
            MuscleProcess(tile, player_ID);
        }
        Table[tile] = player_ID * -1;

        Restsum[RemoveID(tile)]--;



        LastPlayer = player_ID;
}

void Guard_Eat(short player_ID, short *tile)
{
    for (short i = 0; i < 3; i++)
    {
        if(tile[i] == LastThrow) continue;

        if (player_ID == currentGame.playerSelf)
        {
            RemoveHand(tile[i]);
        }

        Table[tile[i]] = player_ID;

        if (GetType(tile[i]) != 4)
            HeatProcess(tile[i]);

        Restsum[RemoveID(tile[i])]--;
    }
    // drawtime 0
    DrawTimeZero(LastThrow, 0);

    LastThrow = 0;
}

void Guard_Pong(short player_ID, short *tile)
{
    for (short i = 0; i < 3; i++)
    {
        if (player_ID == currentGame.playerSelf)
            RemoveHand(tile[i]);

        if(tile[i] == LastThrow) continue;

        Table[tile[i]] = player_ID;

        if (GetType(tile[i]) != 4)
            HeatProcess(tile[i]);

        Restsum[RemoveID(tile[i])]--;
    }

    LastThrow = 0;
}

void Guard_Gong(short player_ID, short *tile, short Gtype)
{
    // drawtime+
    DrawTimePlus(player_ID);

    for (short i = 0; i < ((Gtype != 1)? 4 : 1); i++)
    {
        if (player_ID == currentGame.playerSelf)
        RemoveHand(tile[i]);

        if (tile[i] == LastThrow || Gtype == 0) continue;//若為暗槓則跳過
        
        Table[tile[i]] = player_ID;

        if (GetType(tile[i]) != 4)
            HeatProcess(tile[i]);
    }
    LastThrow = 0;
}

/*************************************************************************/

void SetHand(const short *tile_arr)
{            
    //if莊家 17張手牌, else 16張手牌
    if(currentGame.playerSelf == currentGame.Master)
        Hand_size = 17;
    else
        Hand_size = 16;

    for(short i = 0; i < Hand_size; i++)
    {
        Hand[i] = tile_arr[i];

        Table[tile_arr[i]] = currentGame.playerSelf;
    }
}

void addHand(short tile)
{
    Table[tile] = currentGame.playerSelf;
    Hand[Hand_size++] = tile;
}

void RemoveHand(short tile)
{
    short temp;
    for (temp = 0; temp < Hand_size; temp++)
        if (Hand[temp] == tile)
            break;
    if(temp != Hand_size)
    {
        Table[Hand[temp]] = currentGame.playerSelf * -1;
        Hand[temp] = Hand[Hand_size-1];
        Hand[--Hand_size] = 0;
//cout << "Removed " << tile << " from Hand, Hand size = " << Hand_size << endl;
    }
}

void DrawTimePlus(short player_ID)
{            
    for (short i = 11; i <= 47; i++)
        if (Drawtime[i][player_ID] != -1)
            Drawtime[i][player_ID]++;
}

void DrawTimeZero(short tile, short player_ID) //player_ID = 0 for all player_ID except self
{
    if (player_ID == 0)
        for (short p = 1; p <= 4; p++)
            if (p != currentGame.playerSelf)
                Drawtime[RemoveID(tile)][p] = 0;
    else
        Drawtime[RemoveID(LastThrow)][player_ID] = 0;
}

bool TimeCheck(short *t_max, short *t_sum)
{
    bool throwEnd = false;
    for (short i = 0; i < Hand_size; i++)
    {
        for (short p = 1; p <= 4; p++)
            if (p != currentGame.playerSelf)
            {
                if (Drawtime[RemoveID(Hand[i])][p] > t_max[i])
                    t_max[i] == Drawtime[RemoveID(Hand[i])][p];

                if (Drawtime[RemoveID(Hand[i])][p] > -1)
                    t_sum[i] += Drawtime[RemoveID(Hand[i])][p];
            }
        if (t_sum[i] != -1) t_sum[i]++;

        if (t_max[i] == 0) //follow throw, surely safe
        {
            if (!throwEnd)
            {
                tothrow = Hand[i];
                throwEnd = true;
// cout << "time check throw" << endl;
            }
            else if ( (GetType(Hand[i]) != 4 && GetType(tothrow) == 4) || // 數牌 > 字牌
                        (Restsum[RemoveID(Hand[i])] > Restsum[RemoveID(tothrow)]) ) // 剩張多 > 剩張少
            {
                tothrow = Hand[i];
            }
        }
    }
    return throwEnd;
}

bool SumCheck(short *minsum_ptr, const short *reps)
{
    for (short i = 0; i < Hand_size; i++)
    {
        if (GetType(Hand[i]) == 4)
        {
            short s = Restsum[RemoveID(Hand[i])] - reps[RemoveID(Hand[i])];
// cout << "s: " << s << endl;
            if (s == 0)
            {
                tothrow = Hand[i];
                *minsum_ptr = s;
//cout << "total sum throw" << endl;
                return true;
            }
            else if (s < *minsum_ptr)
            {
                *minsum_ptr = s;
                tothrow = Hand[i];
            }
        }
    }
    return false;
}

short HeatCalculation(const short *t_sum)
{
    short endHeat = 0, minHeat = initial_heat37*3 + 1;
    short htothrow = 0;
    for (short i = 0; i < Hand_size; i++)
    {
        if (GetType(Hand[i]) == 4) continue; //no heat for char tile
//cout << "(num)current tile: " << Hand[i];
        endHeat = 0;
        for (short p = 1; p <= 4; p++)
            if (p != currentGame.playerSelf)
            {
                endHeat += /*(muscle[RemoveID(Hand[i])] != 0 &&
                            Drawtime[RemoveID(muscle[Hand[i]])][p] == 0)?*/
                           (GetType(LastThrow) == GetType(Hand[i]) &&
                            abs(GetDigit(LastThrow)-GetDigit(Hand[i])) == 3 &&
                            muscle[RemoveID(Hand[i])] != 0)?
                            MuscleHeat(Hand[i], p) : Heat[RemoveID(Hand[i])];
// , cout << (GetType(LastThrow) == GetType(Hand[i])) << " " <<
// (abs(GetDigit(LastThrow)-GetDigit(Hand[i])) == 3) << " " <<
// muscle[RemoveID(Hand[i])] << endl;
            }

        //time calc
        // if (t_max[i] != -1 && t_max[i] <= 3)
        //     endHeat = endHeat * t_max[i] / 3;
        if (t_sum[i] != -1 && t_sum[i] <= 9)
            endHeat = endHeat * t_sum[i] / 9;

// cout << Hand[i] << " endHeat = " << endHeat << " v " << minHeat << endl;
        if (endHeat < minHeat)
        {
            minHeat = endHeat;
            htothrow = Hand[i];
        }
        // else numeric = true;
    }
// cout << "htothrow: " << htothrow << endl;
    return htothrow;
}