---
# System prepended metadata

title: CP1 HW04 參考答案
tags: ["CP1\_", HW04]

---

# HW04 參考答案


## 4.1 Sorting

Credit: 41047029S 林Ｏ可 (TA)

:::spoiler `mysort.c`
```c=
#include "mysort.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// 1. All even numbers should be before odd numbers.
// 2. All odd numbers are in ascending order.
// 3. All even numbers are in descending order.

// if x and y should be swapped, return 1
int _cmp(const void *a, const void *b) {
  // cast to int64_t to avoid overflow on edge cases
  int64_t x = *(int32_t *)a;
  int64_t y = *(int32_t *)b;

  bool x_is_even = (x < 0 ? -x : x) % 2 == 0;
  bool y_is_even = (y < 0 ? -y : y) % 2 == 0;

  if (x_is_even && y_is_even) {
    return y > x ? 1 : -1;
  } else if (!x_is_even && !y_is_even) {
    return x > y ? 1 : -1;
  } else {
    return y_is_even ? 1 : -1;
  }
}

void mysort(int32_t array[], int32_t size) {
  qsort(array, size, sizeof(int32_t), _cmp);
}

void myprint(int32_t array[], int32_t size) {
  for (size_t i = 0; i < size; ++i) {
    printf("%" PRId32 " ", array[i]);
  }
  printf("\n");
}
```
:::

## 4.2 Differential of a Function

Credit: 41247001S 盧Ｏ安

:::spoiler Code
```c
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>

static int64_t flowed = 0;

void sisiu(int64_t array1[],int64_t array2[],int64_t a,int64_t b){
	int64_t num = -1;
	for(int64_t i= 0;i<=a;i++){
		if(array1[i]!=0){
			num = array1[i] > 0 ? array1[i]:-array1[i];
			break;
		}
	}
	if(num==-1)return;
	
	//printf("%d",num);
	for(int64_t i=2;i<=num;i++){
		int32_t done = 1;
		for(int64_t j=0;j<=a;j++){

			if(array1[j]%i){
				done = 0;
				break;
			}
		}
		for(int64_t j=0;j<=b;j++){
			if(array2[j]%i){
				done = 0;
				break;
			}
		}

		if(done){

			for(int64_t j=0;j<=a;j++) array1[j] /= i;
			for(int64_t j=0;j<=b;j++) array2[j] /= i;
			num /= i;
			i -= 1;
		}
		
	}

}

void output_line(int64_t a){

	while(a){
		printf("-");
		a -= 1;
	}
	printf("\n");

}

void countflowed(int64_t array1[],int64_t array2[],int64_t a,int64_t b){

	while(flowed <= a && flowed <= b){
		if(array1[flowed] == array2[flowed] && array2[flowed] == 0) flowed += 1;
		else return;
	}


}

int64_t number_length(int64_t target){

	if(target<0) target *= -1;
	if(target>9) return number_length(target/10) + 1;
	if(target) return 1;
	return 0;
}

int64_t countline(int64_t array1[],int64_t array2[],int64_t a,int64_t b){

	int64_t bigger[2];
	bigger[0] = 0;
	bigger[1] = 0;
	int64_t las = 1;
	for(int64_t i=a;i>=0;i--){


		if(array1[i]){
			if(!las && array1[i] != 0)bigger[0] += 1;
			else if(las&&array1[i]<0) bigger[0] += 1;
			if(i != 0 && array1[i]!=1 && array1[i]!=-1)bigger[0] += number_length(array1[i]);
			else if(i==0)bigger[0] += number_length(array1[i]);
				if(i>1) bigger[0] += number_length(i) + 2;
				else if(i==1) bigger[0] += 1;
			las = 0;
		}

	}
	las = 1;
	for(int64_t i=b;i>=0;i--){


		if(array2[i]){
			if(!las && array2[i] != 0)bigger[1] += 1;
			else if(las&&array2[i]<0) bigger[1] += 1;
			if(i != 0 && array2[i]!=1 && array2[i]!=-1)bigger[1] += number_length(array2[i]);
			else if(i==0)bigger[1] += number_length(array2[i]);
				if(i>1) bigger[1] += number_length(i) + 2;
				else if(i==1) bigger[1] += 1;
			las = 0;
		}

	}
	int64_t answer = 0;
	while(bigger[0]>0|| bigger[1]>0){
		answer += 1;
		bigger[0] -= 1;
		bigger[1] -= 1;
	}
	return answer;

}

void output(int64_t array[],int64_t length){
	int64_t las = 1;
	for(int64_t i=length;i>=0;i--){
		if(!array[i]&&!i&&las)printf("0");

		if(array[i]){
			if(!las && array[i] > 0)printf("+");
			if(i != 0 && array[i]!=1 && array[i]!=-1)printf("%ld",array[i]);
			else if(i==0)printf("%ld",array[i]);
			else if(array[i]==-1) printf("-");
				if(i-flowed>1) printf("x^%ld",i-flowed);
				else if(i-flowed==1) printf("x");
			las = 0;
		}

	}
	printf("\n");


}

int main(){

	long double ld_degree[2];
	int64_t degree[2];
	int32_t errors = 0;
	char temps[1000];
	

	printf("Please enter f(x) degree: ");
	scanf("%LF",&ld_degree[0]);
	
		if(ld_degree[0]!=(int64_t)ld_degree[0] || ld_degree[0]<0 || ld_degree[0] > 4294967295){
			errors = 1;
			if(errors){
		printf("Error Input, the degree is invalid!\n");
		return 0;
	}
		}
		else{
			degree[0] = ld_degree[0];
		}
	long double *ld_f = calloc(degree[0]+1,sizeof(long double));
	printf("Please enter f(x) coefficients: ");
	if(!errors){

		for(int64_t i=ld_degree[0];i>=0;i--) scanf("%LF",&ld_f[i]);
	}

	int32_t more[2] = {0};
	scanf("%[^\n]%n",temps,&more[0]);
	printf("Please enter g(x) degree: ");
	scanf("%LF",&ld_degree[1]);
	
	if(ld_degree[1]!=(int64_t)ld_degree[1] || ld_degree[1]<0 || ld_degree[1] > 4294967295){
			errors = 1;
			if(errors){
		printf("Error Input, the degree is invalid!\n");
		return 0;
	}
		}
		else{
			
			degree[1] = ld_degree[1];
			
		}
	long double *ld_g = calloc(degree[1]+1,sizeof(long double));
	printf("Please enter g(x) coefficients: ");
	if(!errors){

		for(int64_t i=ld_degree[1];i>=0;i--) scanf("%LF",&ld_g[i]);
	}
	scanf("%[^\n]%n",temps,&more[1]);

	
	if(errors){
		printf("Error Input, the degree is invalid!\n");
		return 0;
	}
	if(more[0]-1> 0|| more[1]-1> 0){
		//printf("%d %d",more[0],more[1]);
		printf("Wrong Input, the coefficients are more than degree!\n");
		return 0;
	}

	/*for(int i=0;i<degree[0]+1;i++)printf("%LF ",ld_f[i]);
	printf("\n");
	for(int i=0;i<degree[1]+1;i++)printf("%LF ",ld_g[i]);
	printf("\n");*/

	int64_t **f = calloc(2,sizeof(int64_t *)),**g= calloc(2,sizeof(int64_t *));
	for(int32_t i=0;i<2;i++){
		f[i] = calloc(degree[0]+1,sizeof(int64_t));
		g[i] = calloc(degree[1]+1,sizeof(int64_t));
	}
	
	for(int64_t i=degree[0];i>=0;i--){
		//printf("%LF\n",ld_g[0]);
		if(i==degree[0]&&!ld_f[i]){
			printf("The input is invalid,first coefficients should not be 0.\n");
			return 0;
		}
		if(ld_f[i] < -2147483648 || ld_f[i] > 2147483647 || ld_f[i]!=(int32_t)ld_f[i]){
			printf("The coefficients is out of range!\n");
			printf("%LF %d",ld_f[i],(int32_t)ld_f[i]);
			return 0;
		}
		f[0][i] = ld_f[i];
		if(i!=0){
			f[1][i-1] = f[0][i] * (i);
		}
	}
	//printf("%LF\n",ld_g[0]);

	for(int64_t i=degree[1];i>=0;i--){
		//printf("%LF %ld\n",ld_g[i],i);
		if(i==degree[1]&&!ld_g[i]){
			printf("The input is invalid,first coefficients should not be 0.\n");
			return 0;
		}
		if(ld_g[i] < -2147483648 || ld_g[i] > 2147483647|| ld_g[i]!=(int32_t)ld_g[i]){
			printf("The coefficients is out of range!\n");
			printf("%LF %d",ld_g[i],(int32_t)ld_g[i]);
			return 0;
		}
		g[0][i] = ld_g[i];
		if(i!=0){
			g[1][i-1] = g[0][i] * (i);
		}
	}



	printf("f(x): ");
	output(f[0],degree[0]);
	printf("g(x): ");
	output(g[0],degree[1]);

	int64_t *multiply_ = calloc(degree[0] + degree[1] + 1,sizeof(int64_t));
	int64_t *fded_mulg = calloc(degree[0] + degree[1] + 1,sizeof(int64_t));
	int64_t *gded_mulf = calloc(degree[0] + degree[1] + 1,sizeof(int64_t));
	
	for(int64_t i=0;i<degree[0] + degree[1] + 1;i++){
		multiply_[i] = 0;
		fded_mulg[i] = 0;
		gded_mulf[i] = 0;
	}
	
	for(int64_t i=degree[0]-1;i>=0;i--){
		for(int64_t j=degree[1];j>=0;j--){
			fded_mulg[i+j] += f[1][i] * g[0][j];
			multiply_[i+j] += f[1][i]  *g[0][j];
		}
	}

	for(int64_t i=degree[1]-1;i>=0;i--){
		for(int64_t j=degree[0];j>=0;j--){
			gded_mulf[i+j] += g[1][i] * f[0][j];
			multiply_[i+j] += g[1][i] * f[0][j];
		}
	}


	printf("(f(x)g(x))': ");
	output(multiply_,degree[0] + degree[1]);

	int64_t *mul_gg = calloc(degree[1] + degree[1] + 1,sizeof(int64_t));
	for(int64_t i=0;i<degree[1]+degree[1]+1;i++) mul_gg[i] = 0;
	for(int64_t i=degree[1];i>=0;i--){
		for(int64_t j=degree[1];j>=0;j--){
			mul_gg[i+j] += g[0][i] * g[0][j];
		}
	}
	for(int64_t i=0;i<degree[0] + degree[1] + 1;i++){
		multiply_[i] -= gded_mulf[i]; 
		multiply_[i] -= gded_mulf[i]; 
	}

	
	countflowed(multiply_,mul_gg,degree[0] + degree[1],degree[1] + degree[1]);
	sisiu(multiply_,mul_gg,degree[0] + degree[1],degree[1] + degree[1]);
	printf(" f(x)    ");
	if(!countline(multiply_,multiply_,degree[0] + degree[1],degree[0] + degree[1])){
		printf("0\n");
	}
	else{
		output(multiply_,degree[0] + degree[1]);
	}
	
	
	printf("(----)': ");
	
	output_line(countline(multiply_,mul_gg,degree[0] + degree[1],degree[1] + degree[1]));
	printf(" g(x)    ");
	output(mul_gg,degree[1] + degree[1]);

	//output(mul_gg,degree[1] + degree[1] + 1);
}
```
:::

## 4.3 GSAT

Credit: 41247007S 邱Ｏ婷 (revised by TA)

:::spoiler hw0403.c

```c=
#include <stdio.h>
#include <stdint.h>
#include "gsat.h"
#include <stdlib.h>

#define NUM_SUBJECTS 6

void sortScores(int32_t scores[], int size) {
    for (int i = 0; i < size - 1; i++) {
        for (int j = 0; j < size - i - 1; j++) {
            if (scores[j] < scores[j + 1]) {
                int32_t temp = scores[j];
                scores[j] = scores[j + 1];
                scores[j + 1] = temp;
            }
        }
    }
}

void printPercentileScore(int32_t scores[][NUM_SUBJECTS], int studentNumber, int subject, double percentile) {
    int32_t tempScores[STUDENT_NUMBER];
    for (int i = 0; i < studentNumber; i++) {
        tempScores[i] = scores[i][subject];
    }

    sortScores(tempScores, studentNumber);

    // Computing the index for the percentile, adjusted for zero-based array indexing
    int index = (int)(percentile / 100 * studentNumber) - 1;
    index = (percentile / 100 * studentNumber) > index ? index + 1 : index;

    // Boundary check to avoid array out-of-bounds access
    index = index < 0 ? 0 : index;
    index = index >= studentNumber ? studentNumber - 1 : index;

    printf(subject == 0 ? "%5d " : "%9d ", tempScores[index]);
}

int main() {
    int studentNumber = sizeof(score) / sizeof(score[0]);
    double percentiles[] = {12, 25, 50, 75, 88};
    printf("        CHINESE | ENGLISH | MATH_A  | MATH_B  | SOCIAL  | SCIENCE\n");
    for (int i = 0; i < sizeof(percentiles) / sizeof(percentiles[0]); i++) {
        printf("TOP %.0f%% ", percentiles[i]);
        for (int j = 0; j < NUM_SUBJECTS; j++) {
            printPercentileScore(score, studentNumber, j, percentiles[i]);
        }
        printf("\n");
    }
    return 0;
}
```

:::

## 4.4 Xiangqi

Credit: 41247014S 李Ｏ達

:::spoiler mychess.c
```c
#include"mychess.h"

int32_t checkmate( int32_t board[10][9] )
{
    //檢查棋盤是否有效
    int32_t check_board[18];
    for ( int32_t i = 0; i < 18; i++ )
    {
        check_board[i] = 0;
    }
    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] < 0 || (board[i][j] > RED_SOLDIER && board[i][j] < BLACK_GENERAL) || board[i][j] > BLACK_SOLDIER )
                return -1;
            else
                check_board[board[i][j]] += 1;
            if ( board[i][j] == RED_GENERAL && (i>2 || j<3 || j>5) )//檢查紅將軍位置
                return -1;
            if ( board[i][j] == BLACK_GENERAL && (i<7 || j<3 || j>5) )//檢查黑將軍位置
                return -1;
            if ( board[i][j] == RED_ADVISOR )//檢查紅士位置
            {
                if( i == 0 && ( j==3 || j==5 ) )
                    continue;
                else if( i == 1 && j == 4 )
                    continue;
                else if( i == 2 && ( j==3 || j==5 ) )
                    continue;
                else
                    return -1;
            }
            if ( board[i][j] == BLACK_ADVISOR )//檢查黑士位置
            {
                if( i == 7 && ( j==3 || j==5 ) )
                    continue;
                else if( i == 8 && j == 4 )
                    continue;
                else if( i == 9 && ( j==3 || j==5 ) )
                    continue;
                else
                    return -1;
            }
            if ( board[i][j] == RED_ELEPHANT )//檢查紅象位置
            {
                if( i == 0 && ( j==2 || j==6 ) )
                    continue;
                else if( i == 2 && ( j==0 || j==4 || j==8 ) )
                    continue;
                else if( i == 4 && ( j==2 || j==6 ) )
                    continue;
                else
                    return -1;
            }
            if ( board[i][j] == BLACK_ELEPHANT )//檢查黑象位置
            {
                if( i == 5 && ( j==2 || j==6 ) )
                    continue;
                else if( i == 7 && ( j==0 || j==4 || j==8 ) )
                    continue;
                else if( i == 9 && ( j==2 || j==6 ) )
                    continue;
                else
                    return -1;
            }
            if ( board[i][j] == RED_SOLDIER )//檢查紅兵位置
            {
                if( (i == 3 || i == 4) && ( j==0 || j==2 || j == 4 || j == 6 || j == 8 ) )
                    continue;
                else if ( i >= 5 && i <= 9 )
                    continue;
                else return -1;
            }
            if ( board[i][j] == BLACK_SOLDIER )//檢查黑兵位置
            {
                if( (i == 5 || i == 6) && ( j==0 || j==2 || j == 4 || j == 6 || j == 8 ) )
                    continue;
                else if ( i >= 0 && i <= 4 )
                    continue;
                else return -1;
            }
        }
    }
    for ( int32_t i = 0; i < 18; i++ )//檢查棋子數量
    {
        if ( i == RED_GENERAL || i== BLACK_GENERAL )
        {
            if ( check_board[i] != 1 )
                return -1;
        }
        else if ( (i >= RED_ADVISOR && i <= RED_CANNON) || (i >= BLACK_ADVISOR && i <= BLACK_CANNON) )
        {
            if ( check_board[i] > 2 )
                return -1;
        }
        else if ( i==RED_SOLDIER || i == BLACK_SOLDIER )
        {
            if ( check_board[i] > 5 )
                return -1;
        }
    }
    //輸出
    int32_t check_general = 0, check_horse = 0, check_chariot = 0, check_cannon = 0, check_soldier = 0;
    int32_t *check_general_ptr = &check_general, *check_horse_ptr = &check_horse, *check_chariot_ptr = &check_chariot, *check_cannon_ptr = &check_cannon, *check_soldier_ptr = &check_soldier;
    int32_t ans_general[5][2]={0}, ans_horse[5][2]={0}, ans_chariot[5][2]={0}, ans_cannon[5][2]={0}, ans_soldier[5][2]={0};
    int32_t number = 1;

    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] == RED_GENERAL )
            {
                if ( MOVE_GENERAL(i,j,1,board,ans_general,check_general_ptr) == 1 )
                {
                    for ( int32_t k=0; k<*check_general_ptr; k++ )
                    {
                        printf("%d) Move General from (%d,%d) to (%d,%d)\n", number, i, j, ans_general[k][0], ans_general[k][1] );
                        number += 1;
                    }
                    *check_general_ptr = 0;
                }
            }
        }
    }
    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] == RED_HORSE )
            {
                if ( MOVE_HORSE(i,j,1,board,ans_horse,check_horse_ptr) == 1 )
                {
                    for ( int32_t k=0; k<*check_horse_ptr; k++ )
                    {
                        printf("%d) Move Horse from (%d,%d) to (%d,%d)\n", number, i, j, ans_horse[k][0], ans_horse[k][1] );
                        number += 1;
                    }
                    *check_horse_ptr = 0;
                }
            }
        }
    }
    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] == RED_CHARIOT )
            {
                if ( MOVE_CHARIOT(i,j,board,ans_chariot,check_chariot_ptr) == 1 )
                {
                    for ( int32_t k=0; k<*check_chariot_ptr; k++ )
                    {
                        printf("%d) Move Chariot from (%d,%d) to (%d,%d)\n", number, i, j, ans_chariot[k][0], ans_chariot[k][1] );
                        number += 1;
                    }
                    *check_chariot_ptr = 0;
                }
            }
        }
    }
    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] == RED_CANNON )
            {
                if ( MOVE_CANNON(i,j,board,ans_cannon,check_cannon_ptr) == 1 )
                {
                    for ( int32_t k=0; k<*check_cannon_ptr; k++ )
                    {
                        printf("%d) Move Cannon from (%d,%d) to (%d,%d)\n", number, i, j, ans_cannon[k][0], ans_cannon[k][1] );
                        number += 1;
                    }
                    *check_cannon_ptr = 0;
                }
            }
        }
    }
    for ( int32_t i = 0; i < 10; i++ )
    {
        for ( int32_t j = 0; j < 9; j++ )
        {
            if ( board[i][j] == RED_SOLDIER )
            {
                if ( MOVE_SOLDIER(i,j,1,board,ans_soldier,check_soldier_ptr) == 1 )
                {
                    for ( int32_t k=0; k<*check_soldier_ptr; k++ )
                    {
                        printf("%d) Move Soldier from (%d,%d) to (%d,%d)\n", number, i, j, ans_soldier[k][0], ans_soldier[k][1] );
                        number += 1;
                    }
                    *check_soldier_ptr = 0;
                }
            }
        }
    }
}

int32_t MOVE_GENERAL( int32_t x , int32_t y ,int32_t times, int32_t board[10][9] , int32_t ans_general[5][2], int32_t *check_general_ptr)
{
    int32_t walk[2][2] = { {0,1}, {0,-1} };
    for ( int32_t i = 0; i < 2; i++ )
    {
        if ( times == 1 )
        {
            int32_t tmpx = x + walk[i][0];
            int32_t tmpy = y + walk[i][1];
            if ( tmpx<0 || tmpx>2 || tmpy<3 || tmpy>5 )
                continue;
            if ( board[tmpx][tmpy]>=RED_GENERAL && board[tmpx][tmpy]<=RED_SOLDIER )
                continue;
            MOVE_GENERAL( tmpx, tmpy, 2, board, ans_general, check_general_ptr );
        }
        if ( times == 2 )
        {
            for ( int32_t j = x+1; j<10 ; j++ )
            {
                if ( board[j][y] == BLACK_GENERAL )
                {
                    ans_general[*check_general_ptr][0] = x;
                    ans_general[*check_general_ptr][1] = y;
                    *check_general_ptr += 1;
                    return 0;
                }
                else if ( board[j][y] != EMPTY )
                    return 0;
            }
        }
    }
    if ( *check_general_ptr != 0 )
        return 1;
    else
        return 0;
}

int32_t MOVE_HORSE( int32_t x, int32_t y,int32_t times, int32_t board[10][9], int32_t ans_horse[5][2], int32_t *check_horse_ptr)
{
    int32_t walk[8][2] = { {-2,-1}, {-2,1}, {-1,-2}, {-1,2}, {1,-2}, {1,2}, {2,-1}, {2,1} };
    int32_t leg[8][2] = { {-1,0}, {-1,0}, {0,-1}, {0,1}, {0,-1}, {0,1}, {1,0}, {1,0} };
    for ( int32_t i = 0; i < 8; i++ )
    {
        int32_t tmpx = x + walk[i][0];
        int32_t tmpy = y + walk[i][1];
        int32_t tmplegx = x + leg[i][0];
        int32_t tmplegy = y + leg[i][1];
        if ( tmpx<0 || tmpx>9 || tmpy<0 || tmpy>8 )
            continue;
        if ( board[tmpx][tmpy]>=RED_GENERAL && board[tmpx][tmpy]<=RED_SOLDIER )
            continue;
        if ( board[tmplegx][tmplegy] != EMPTY )
            continue;
        if ( times == 1 )
            MOVE_HORSE( tmpx, tmpy, 2, board, ans_horse, check_horse_ptr );
        if ( times == 2 )
        {
            if ( board[tmpx][tmpy] == BLACK_GENERAL )
            {
                ans_horse[*check_horse_ptr][0] = x;
                ans_horse[*check_horse_ptr][1] = y;
                *check_horse_ptr += 1;
                return 0;
            }
            else
                continue;
        }
    }
    if ( *check_horse_ptr != 0 )
        return 1;
    else
        return 0;
}

int32_t MOVE_CHARIOT( int32_t x, int32_t y, int32_t board[10][9], int32_t ans_chariot[5][2] , int32_t *check_chariot_ptr)
{
    int32_t block=0;
    for ( int32_t i=x-1 ; i>=0 ; i-- )
    {
        if ( board[i][y]>=RED_GENERAL && board[i][y]<=RED_SOLDIER )
            break;
        if ( board[i][y]>=BLACK_GENERAL && board[i][y]<=BLACK_SOLDIER )
            block += 1;
        if ( block > 1 )
            break;
        else
            CHARIOT_EAT_GENERAL( i, y, board, ans_chariot, check_chariot_ptr );
    }
    block = 0;
    for ( int32_t i=y-1 ; i>=0 ; i-- )
    {
        if ( board[x][i]>=RED_GENERAL && board[x][i]<=RED_SOLDIER )
            break;
        if ( board[x][i]>=BLACK_GENERAL && board[x][i]<=BLACK_SOLDIER )
            block += 1;
        if ( block > 1 )
            break;
        else
            CHARIOT_EAT_GENERAL( x, i, board, ans_chariot, check_chariot_ptr );
    }
    block = 0;
    for ( int32_t i=y+1 ; i<=8 ; i++ )
    {
        if ( board[x][i]>=RED_GENERAL && board[x][i]<=RED_SOLDIER )
            break;
        if ( board[x][i]>=BLACK_GENERAL && board[x][i]<=BLACK_SOLDIER )
            block += 1;
        if ( block > 1 )
            break;
        else
            CHARIOT_EAT_GENERAL( x, i, board, ans_chariot, check_chariot_ptr );
    }
    block = 0;
    for ( int32_t i=x+1 ; i<=9 ; i++ )
    {
        if ( board[i][y]>=RED_GENERAL && board[i][y]<=RED_SOLDIER )
            break;
        if ( board[i][y]>=BLACK_GENERAL && board[i][y]<=BLACK_SOLDIER )
            block += 1;
        if ( block > 1 )
            break;
        else
            CHARIOT_EAT_GENERAL( i, y, board, ans_chariot, check_chariot_ptr );
    }
    if ( *check_chariot_ptr != 0 )
        return 1;
    else
        return 0;
}

int32_t MOVE_CANNON( int32_t x, int32_t y, int32_t board[10][9], int32_t ans_cannon[5][2] , int32_t *check_cannon_ptr)
{
    int32_t block=0;
    for ( int32_t i=x-1 ; i >= 0 ; i-- )
    {
        if ( board[i][y]!= 0 )
            block += 1;
        if ( block == 0 )
            CANNON_EAT_GENERAL( i, y, board, ans_cannon, check_cannon_ptr );
        if ( block == 1 )
        {
            int32_t landing_point=0;
            for ( int32_t j=i-1 ; j >= 0 ; j-- )
            {
                if ( board[j][y]!= EMPTY )
                    landing_point += 1;
                if ( landing_point==1 && board[j][y]>=BLACK_GENERAL && board[j][y]<=BLACK_SOLDIER )
                {
                    CANNON_EAT_GENERAL( j, y, board, ans_cannon, check_cannon_ptr );
                    break;
                }
                if ( landing_point > 1 )
                    break;
            }
            break;
        }
    }
    block=0;
    for ( int32_t i=y-1 ; i >= 0 ; i-- )
    {
        if ( board[x][i]!= 0 )
            block += 1;
        if ( block == 0 )
            CANNON_EAT_GENERAL( x, i, board, ans_cannon, check_cannon_ptr );
        if ( block == 1 )
        {
            int32_t landing_point=0;
            for ( int32_t j=i-1 ; j >= 0 ; j-- )
            {
                if ( board[x][j]!= EMPTY )
                    landing_point += 1;
                if ( landing_point==1 && board[x][j]>=BLACK_GENERAL && board[x][j]<=BLACK_SOLDIER )
                {
                    CANNON_EAT_GENERAL( x, j, board, ans_cannon, check_cannon_ptr );
                    break;
                }
                if ( landing_point > 1 )
                    break;
            }
            break;
        }
    }
    block=0;
    for ( int32_t i=y+1 ; i <= 8 ; i++ )
    {
        if ( board[x][i]!= 0 )
            block += 1;
        if ( block == 0 )
            CANNON_EAT_GENERAL(x,i,board,ans_cannon,check_cannon_ptr);
        if ( block == 1 )
        {
            int32_t landing_point=0;
            for ( int32_t j=i+1 ; j < 8 ; j++ )
            {
                if ( board[x][j]!= EMPTY )
                    landing_point += 1;
                if ( landing_point==1 && board[x][j]>=BLACK_GENERAL && board[x][j]<=BLACK_SOLDIER )
                {
                    CANNON_EAT_GENERAL(x,j,board,ans_cannon,check_cannon_ptr);
                    break;
                }
                if ( landing_point > 1 )
                    break;
            }
            break;
        }
    }
    block=0;
    for ( int32_t i=x+1 ; i <= 9 ; i++ )
    {
        if ( board[i][y]!= 0 )
            block += 1;
        if ( block == 0 )
            CANNON_EAT_GENERAL(i,y,board,ans_cannon,check_cannon_ptr);
        if ( block == 1 )
        {
            int32_t landing_point=0;
            for ( int32_t j=i+1 ; j < 9 ; j++ )
            {
                if ( board[j][y]!= EMPTY )
                    landing_point += 1;
                if ( landing_point==1 && board[j][y]>=BLACK_GENERAL && board[j][y]<=BLACK_SOLDIER )
                {
                    CANNON_EAT_GENERAL(j,y,board,ans_cannon,check_cannon_ptr);
                    break;
                }
                if ( landing_point > 1 )
                    break;
            }
            break;
        }
    }
    if ( *check_cannon_ptr != 0 )
        return 1;
    else
        return 0;
}

int32_t MOVE_SOLDIER( int32_t x, int32_t y, int32_t times, int32_t board[10][9], int32_t ans_soldier[5][2], int32_t *check_soldier_ptr )
{
    int32_t walk[3][2] = { {0,-1}, {0,1}, {1,0} };
    for ( int32_t i = 0; i < 3; i++ )
    {
        int32_t tmpx = x + walk[i][0];
        int32_t tmpy = y + walk[i][1];
        if ( tmpx<0 || tmpx>9 || tmpy<0 || tmpy>8 )
            continue;
        if ( board[tmpx][tmpy]>=RED_GENERAL && board[tmpx][tmpy]<=RED_SOLDIER )
            continue;
        if ( times == 1 )
            MOVE_SOLDIER( tmpx, tmpy, 2, board, ans_soldier, check_soldier_ptr );
        if ( times == 2 )
        {
            if ( board[tmpx][tmpy] == BLACK_GENERAL )
            {
                ans_soldier[*check_soldier_ptr][0] = x;
                ans_soldier[*check_soldier_ptr][1] = y;
                *check_soldier_ptr += 1;
                return 0;
            }
            else
                continue;
        }
    }
    if ( *check_soldier_ptr != 0 )
        return 1;
    else
        return 0;
}

int32_t CHARIOT_EAT_GENERAL(int32_t x, int32_t y, int32_t board[10][9], int32_t ans_chariot[5][2], int32_t *check_chariot_ptr)
{
    for ( int32_t i=x-1 ; i>=0 ; i-- )
    {
        if ( board[i][y]!=EMPTY && board[i][y]!=BLACK_GENERAL )
            break;
        if ( board[i][y] == BLACK_GENERAL )
        {
            ans_chariot[*check_chariot_ptr][0] = x;
            ans_chariot[*check_chariot_ptr][1] = y;
            *check_chariot_ptr += 1;
            return 0;
        }
    }
    for ( int32_t i=y-1 ; i>=0 ; i-- )
    {
        if ( board[x][i]!=EMPTY && board[x][i]!=BLACK_GENERAL )
            break;
        if ( board[x][i] == BLACK_GENERAL )
        {
            ans_chariot[*check_chariot_ptr][0] = x;
            ans_chariot[*check_chariot_ptr][1] = y;
            *check_chariot_ptr += 1;
            return 0;
        }
    }
    for ( int32_t i=y+1 ; i<=8 ; i++ )
    {
        if ( board[x][i]!=EMPTY && board[x][i]!=BLACK_GENERAL )
            break;
        if ( board[x][i] == BLACK_GENERAL )
        {
            ans_chariot[*check_chariot_ptr][0] = x;
            ans_chariot[*check_chariot_ptr][1] = y;
            *check_chariot_ptr += 1;
            return 0;
        }
    }
    for ( int32_t i=x+1 ; i<=9 ; i++ )
    {
        if ( board[i][y]!=EMPTY && board[i][y]!=BLACK_GENERAL )
            break;
        if ( board[i][y] == BLACK_GENERAL )
        {
            ans_chariot[*check_chariot_ptr][0] = x;
            ans_chariot[*check_chariot_ptr][1] = y;
            *check_chariot_ptr += 1;
            return 0;
        }
    }
}

int32_t CANNON_EAT_GENERAL(int32_t x, int32_t y, int32_t board[10][9], int32_t ans_cannon[5][2], int32_t *check_cannon_ptr)
{
    int32_t block=0;
    for ( int32_t i=x-1 ; i>=0 ; i-- )
    {
        if ( board[i][y] != EMPTY )
            block += 1;
        if ( board[i][y]== RED_CANNON )
            block -= 1;
        if ( block>2 )
            break;
        if ( block == 2 && board[i][y] == BLACK_GENERAL )
        {
            ans_cannon[*check_cannon_ptr][0] = x;
            ans_cannon[*check_cannon_ptr][1] = y;
            *check_cannon_ptr += 1;
            return 0;
        }
    }
    block = 0;
    for ( int32_t i=y-1 ; i>=0 ; i-- )
    {
        if ( board[x][i]!= EMPTY )
            block += 1;
        if ( board[x][i]== RED_CANNON )
            block -= 1;
        if ( block>2 )
            break;
        if ( block == 2 && board[x][i] == BLACK_GENERAL )
        {
            ans_cannon[*check_cannon_ptr][0] = x;
            ans_cannon[*check_cannon_ptr][1] = y;
            *check_cannon_ptr += 1;
            return 0;
        }
    }
    block = 0;
    for ( int32_t i=y+1 ; i<=8 ; i++ )
    {
        if ( board[x][i]!= EMPTY )
            block += 1;
        if ( board[x][i]== RED_CANNON )
            block -= 1;
        if ( block>2 )
            break;
        if ( block == 2 && board[x][i] == BLACK_GENERAL )
        {
            ans_cannon[*check_cannon_ptr][0] = x;
            ans_cannon[*check_cannon_ptr][1] = y;
            *check_cannon_ptr += 1;
            return 0;
        }
    }
    block = 0;
    for ( int32_t i=x+1 ; i<=9 ; i++ )
    {
        if ( board[i][y]!= EMPTY )
            block += 1;
        if ( board[i][y]== RED_CANNON )
            block -= 1;
        if ( block>2 )
            break;
        if ( block == 2 && board[i][y] == BLACK_GENERAL )
        {
            ans_cannon[*check_cannon_ptr][0] = x;
            ans_cannon[*check_cannon_ptr][1] = y;
            *check_cannon_ptr += 1;
            return 0;
        }
    }
}
```
:::

:::spoiler mychess.h
```c
#pragma once
#include<stdint.h>
#include<stdio.h>
#include<stdlib.h>

#define EMPTY (0)
#define RED_GENERAL (1)
#define RED_ADVISOR (2)
#define RED_ELEPHANT (3)
#define RED_HORSE (4)
#define RED_CHARIOT (5)
#define RED_CANNON (6)
#define RED_SOLDIER (7)
#define BLACK_GENERAL (11)
#define BLACK_ADVISOR (12)
#define BLACK_ELEPHANT (13)
#define BLACK_HORSE (14)
#define BLACK_CHARIOT (15)
#define BLACK_CANNON (16)
#define BLACK_SOLDIER (17)

int32_t checkmate( int32_t board[10][9] );
int32_t MOVE_GENERAL( int32_t x , int32_t y ,int32_t times, int32_t board[10][9] , int32_t ans_general[5][2], int32_t *check_general_ptr);
int32_t MOVE_HORSE( int32_t x, int32_t y,int32_t times, int32_t board[10][9], int32_t ans_horse[5][2], int32_t *check_horse_ptr);
int32_t MOVE_CHARIOT( int32_t x, int32_t y, int32_t board[10][9], int32_t ans_chariot[5][2] , int32_t *check_chariot_ptr);
int32_t MOVE_CANNON( int32_t x, int32_t y, int32_t board[10][9], int32_t ans_cannon[5][2] , int32_t *check_cannon_ptr);
int32_t MOVE_SOLDIER( int32_t x, int32_t y, int32_t times, int32_t board[10][9], int32_t ans_soldier[5][2], int32_t *check_soldier_ptr );
int32_t CHARIOT_EAT_GENERAL(int32_t x, int32_t y, int32_t board[10][9], int32_t ans_chariot[5][2], int32_t *check_chariot_ptr);
int32_t CANNON_EAT_GENERAL(int32_t x, int32_t y, int32_t board[10][9], int32_t ans_cannon[5][2], int32_t *check_cannon_ptr);

```
:::

## 4.5 Japanese Mahjong
Credit: 41247039S 韓Ｏ劭

:::spoiler hw0405.c
```c
#include <stdio.h>
#include <stdint.h>
#include "mahjong.h"

int main() {
	myMahjong mahjong = { {0}, {0}, { {0},{0} }, 0, 0, 0, 0, 0 };

	// Hand input

	int32_t meld = 0, validHand = 1;
	while (meld != 4) {
		printf("Please input meld: ");

		int32_t tile = 0, count = 0;
		while (count <= 14) {
			if (scanf("%d", &tile) != 1 || !isValidNewTile(mahjong, tile)) {
				if (tile != 0) {
					validHand = 0;
				}
				break;
			}

			mahjong.tilesAmount[tile]++;
			mahjong.tiles[mahjong.totalTiles++] = tile;
			count++;
		}

		mahjong.melds[meld][MELD_TILES] = mahjong.totalTiles;
		int32_t check = isValidMeld(mahjong, meld);
		// printf("check=%d, total=%d\n", check, mahjong.totalTiles);
		if (validHand == 0 || check == 0) {
			validHand = 0;
			meld = -1;
			break;
		} else if (check == 2) {
			meld = 1;
			break;
		}

		printf("Is open group(1: YES 0: NO): ");

		int32_t openMeld = 0;
		if (scanf("%d", &openMeld) != 1 || (openMeld != 0 && openMeld != 1)) {
			validHand = 0;
			meld = -1;
			break;
		}

		mahjong.melds[meld][MELD_OPEN] = openMeld;

		meld++;
	}

	mahjong.totalMelds = meld;

	// Pair input

	if (validHand && meld != 1) {
		printf("Please input pair: ");

		int32_t pair = 0;
		while (pair < 2) {
			int32_t tile = 0;
			if (scanf("%d", &tile) != 1 || !isValidNewTile(mahjong, tile)) {
				validHand = 0;
				break;
			}

			mahjong.tilesAmount[tile]++;
			mahjong.tiles[mahjong.totalTiles++] = tile;

			pair++;
		}
	}

	if (validHand && meld != 1) {
		int32_t pair1 = mahjong.tiles[mahjong.totalTiles - 1];
		int32_t pair2 = mahjong.tiles[mahjong.totalTiles - 2];
		if (!isValidPair(pair1, pair2)) {
			validHand = 0;
		}
	}

	// Winning tile input

	if (validHand) {
		int32_t tile = 0;
		printf("Please input winning tile: ");

		if (scanf("%d", &tile) != 1 || !isValidWinningTile(mahjong, tile)) {
			// printf("Invalid winning tile!\n");
			validHand = 0;
		}

		mahjong.winningTile = tile;
	}

	// Wind input

	if (validHand) {
		int32_t playerWind = 0;
		printf("Player's wind(0:E 1:S 2:W 3:N): ");

		if (scanf("%d", &playerWind) != 1 || !isValidWind(playerWind)) {
			// printf("Invalid player wind!\n");
			validHand = 0;
		}

		mahjong.playerWind = playerWind;
	}

	if (validHand) {
		int32_t prevailingWind = 0;
		printf("Prevailing wind(0:E 1:S 2:W 3:N): ");

		if (scanf("%d", &prevailingWind) != 1 || !isValidWind(prevailingWind)) {
			// printf("Invalid player wind!\n");
			validHand = 0;
		}

		mahjong.prevailingWind = prevailingWind;
	}

	// printf("All tiles: \n");
	// for (int32_t i = 0; i < mahjong.totalMelds; i++) {
	// 	int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
	// 	int32_t tail = mahjong.melds[i][MELD_TILES];

	// 	for (int32_t j = head; j < tail; j++) {
	// 		printf("%d ", mahjong.tiles[j]);
	// 	}
	// 	printf("\n");
	// }

	if (!validHand) {
		mahjong.totalMelds = -1;
	}

	printf("\n");
	calculateHan(mahjong);

	return 0;
}

```
:::

:::spoiler mahjong.c
```c
#include "mahjong.h"

int32_t isValidNewTile(myMahjong mahjong, int32_t tile) {
	if (tile < 1 || tile > 34) {
		return 0;
	}

	if (mahjong.tilesAmount[tile] == 4) {
		return 0;
	}

	return 1;
}

int32_t isValidAmountOfTiles(myMahjong mahjong) {
	int32_t tilesAmount[35] = {0};

	for (int32_t i = 0; i < mahjong.totalTiles; i++) {
		int32_t tile = mahjong.tiles[i];

		tilesAmount[tile]++;

		if (tilesAmount[tile] > 4) {
			return 0;
		}
	}

	return 1;
}

int32_t isValidMeld(myMahjong mahjong, int32_t meld) {
	if (meld < 0 || meld > 4) {
		return 0;
	}

	if (isStraightMeld(mahjong, meld) || isTripletOrKanMeld(mahjong, meld)) {
		return 1;
	}

	if (isSpecialMeld(mahjong, meld)) {
		return 2;
	}

	return 0;
}

int32_t isValidPair(int32_t tile1, int32_t tile2) {
	return (tile1 == tile2);
}

int32_t isValidWinningTile(myMahjong mahjong, int32_t tile) {
	int32_t check = 0;

	if (mahjong.tiles[mahjong.totalTiles-1] == tile) {
		return 1;
	}

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];

		for (int32_t j = head; j < tail; j++) {
			if ((mahjong.tiles[j] == tile) && (isTripletOrKanMeld(mahjong, i) != 2)) {
				check = 1;
				break;
			}
		}
	}

	// printf("check=%d\n", check);

	return check;
}

int32_t isValidWind(int32_t wind) {
	return (wind == 0 || wind == 1 || wind == 2 || wind == 3);
}

void calculateHan(myMahjong mahjong) {
	int32_t result = 0;

	printf("The Score is...\n");

	if (mahjong.totalMelds == -1) {
		printYaku(ERROR_YAKU);
		printf("Total: 0 Han\n");
		return;
	}

	result = handleYakuman(mahjong);

	if (result != 0) {
		printf("Total: %d Yakuman\n", result / 100);
		return;
	}

	result = handleYaku(mahjong);

	if (result == 0) {
		printYaku(NO_YAKU);
	}

	printf("Total: %d Han", result);
	if (result >= 13) {
		printf(" (Kazoe-yakuman)");
	}
	printf("\n");
}

```
:::

:::spoiler mahjong_yaku.c
```c 
#include "mahjong_yaku.h"

int32_t isHonorTile(int32_t tile) {
	return (tile == EAST  || tile == SOUTH ||
			tile == WEST  || tile == NORTH ||
			tile == WHITE || tile == GREEN ||
			tile == RED);
}

int32_t isYaochuTile(int32_t tile) {
	return (tile == PIN_1 || tile == PIN_9 ||
			tile == SO_1  || tile == SO_9  ||
			tile == MAN_1 || tile == MAN_9 ||
			tile == EAST  || tile == SOUTH ||
			tile == WEST  || tile == NORTH ||
			tile == WHITE || tile == GREEN ||
			tile == RED);
}

int32_t isStraightMeld(myMahjong mahjong, int32_t meld) {
	int32_t head  = (meld == 0) ? 0 : mahjong.melds[meld-1][MELD_TILES];
	int32_t tail  = mahjong.melds[meld][MELD_TILES];
	int32_t tiles = tail - head;

	if (tiles != 3) {
		return 0;
	}

	int32_t tempMeld[3] = {0};

	for (int32_t i = head; i < tail; i++) {
		tempMeld[i - head] = mahjong.tiles[i];
	}

	for (int32_t i = 0; i < tiles - 1; i++) {
		for (int32_t j = i + 1; j < tiles; j++) {
			if (tempMeld[i] > tempMeld[j]) {
				int32_t temp = tempMeld[i];
				tempMeld[i]  = tempMeld[j];
				tempMeld[j]  = temp;
			}
		}
	}

	switch (tempMeld[0]) {
		case PIN_8: case PIN_9:
		case SO_8:  case SO_9:
		case MAN_8: case MAN_9:
		case EAST:  case SOUTH: case WEST: case NORTH:
		case WHITE: case GREEN: case RED:
		return 0;
		break;

		default:
		break;
	}

	if ((tempMeld[0] + 1 == tempMeld[1]) && (tempMeld[1] + 1 == tempMeld[2])) {
		// printf("Is straight!\n");
		return 1;
	}

	return 0;
}

int32_t isTripletOrKanMeld(myMahjong mahjong, int32_t meld) {
	int32_t head  = (meld == 0) ? 0 : mahjong.melds[meld-1][MELD_TILES];
	int32_t tail  = mahjong.melds[meld][MELD_TILES];
	int32_t tiles = tail - head;

	if (tiles != 3 && tiles != 4) {
		return 0;
	}

	for (int32_t i = head; i < tail - 1; i++) {
		if (mahjong.tiles[i] != mahjong.tiles[i + 1]) {
			return 0;
		}
	}

	return tiles - 2;
}

int32_t isSpecialMeld(myMahjong mahjong, int32_t meld) {
	int32_t head  = (meld == 0) ? 0 : mahjong.melds[meld-1][MELD_TILES];
	int32_t tail  = mahjong.melds[meld][MELD_TILES];
	int32_t tiles = tail - head;

	if (tiles != 14) {
		return 0;
	}

	if (!isThirteenOrphans(mahjong) && !isSevenPairs(mahjong)) {
		return 0;
	}

	return 1;
}

int32_t isClosedHand(myMahjong mahjong) {
	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (mahjong.melds[i][MELD_OPEN] == 1) {
			return 0;
		}
	}

	return 1;
}

int32_t amountOfHonors(myMahjong mahjong) {
	int32_t total = 0;
	for (int32_t i = EAST; i <= RED; i++) {
		total += mahjong.tilesAmount[i];
	}

	return total;
}

int32_t amountOfTerminals(myMahjong mahjong) {
	int32_t total = 0;

	total += mahjong.tilesAmount[PIN_1];
	total += mahjong.tilesAmount[PIN_9];
	total += mahjong.tilesAmount[SO_1];
	total += mahjong.tilesAmount[SO_9];
	total += mahjong.tilesAmount[MAN_1];
	total += mahjong.tilesAmount[MAN_9];

	return total;
}

int32_t handleYakuman(myMahjong mahjong) {
	int32_t total = 0;

	// 2 Yakuman

	if (isFourWinds(mahjong) == TWO_YAKUMAN) {
		printYaku(BIG_FOUR_WINDS);
		total += TWO_YAKUMAN;
	}

	if (isFourConcealedTriplets(mahjong) == TWO_YAKUMAN) {
		printYaku(FOUR_CONCEALED_TRIPLETS_SINGLE_WAIT);
		total += TWO_YAKUMAN;
	}

	if (isNineGates(mahjong) == TWO_YAKUMAN) {
		printYaku(NINE_GATES_NINE_WAIT);
		total += TWO_YAKUMAN;
	}

	if (isThirteenOrphans(mahjong) == TWO_YAKUMAN) {
		printYaku(THIRTEEN_ORPHANS_13_WAIT);
		total += TWO_YAKUMAN;
	}

	// 1 Yakuman

	if (isAllGreen(mahjong) == ONE_YAKUMAN) {
		printYaku(ALL_GREEN);
		total += ONE_YAKUMAN;
	}

	if (isAllHonors(mahjong) == ONE_YAKUMAN) {
		printYaku(ALL_HONORS);
		total += ONE_YAKUMAN;
	}

	if (isAllTerminals(mahjong) == ONE_YAKUMAN) {
		printYaku(ALL_TERMINALS);
		total += ONE_YAKUMAN;
	}

	if (isBigThreeDragons(mahjong) == ONE_YAKUMAN) {
		printYaku(BIG_THREE_DRAGONS);
		total += ONE_YAKUMAN;
	}

	if (isFourConcealedTriplets(mahjong) == ONE_YAKUMAN) {
		printYaku(FOUR_CONCEALED_TRIPLETS);
		total += ONE_YAKUMAN;
	}

	if (isFourKans(mahjong) == ONE_YAKUMAN) {
		printYaku(FOUR_KANS);
		total += ONE_YAKUMAN;
	}

	if (isFourWinds(mahjong) == ONE_YAKUMAN) {
		printYaku(LITTLE_FOUR_WINDS);
		total += ONE_YAKUMAN;
	}

	if (isNineGates(mahjong) == ONE_YAKUMAN) {
		printYaku(NINE_GATES);
		total += ONE_YAKUMAN;
	}

	if (isThirteenOrphans(mahjong) == ONE_YAKUMAN) {
		printYaku(THIRTEEN_ORPHANS);
		total += ONE_YAKUMAN;
	}

	return total;
}

int32_t isFourWinds(myMahjong mahjong) {
	int32_t triplet = 0, pair = 0;

	for (int32_t i = EAST; i <= NORTH; i++) {
		if (mahjong.tilesAmount[i] >= 3) {
			triplet++;
		} else if (mahjong.tilesAmount[i] == 2) {
			pair++;
		}
	}

	if (triplet == 4 && pair == 0) {
		return TWO_YAKUMAN;
	} else if (triplet == 3 && pair == 1) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isFourConcealedTriplets(myMahjong mahjong) {
	int32_t triplet = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (isTripletOrKanMeld(mahjong, i)) {
			triplet++;
		}
	}

	if (triplet == 4 && isClosedHand(mahjong)) {
		if (mahjong.winningTile == mahjong.tiles[mahjong.totalTiles-1]) {
			return TWO_YAKUMAN;
		} else {
			return ONE_YAKUMAN;
		}
	}

	return 0;
}

int32_t isNineGates(myMahjong mahjong) {
	if (!isClosedHand(mahjong)) {
		return 0;
	}

	for (int32_t i = 0; i < 3; i++) {
		int32_t check = 0, nineWait = 0;

		for (int32_t j = 1; j <= 9; j++) {
			int32_t tile   = i * 9 + j;
			int32_t amount = mahjong.tilesAmount[tile];

			if ((j == 1 || j == 9) && amount >= 3) {
				check++;

				if (amount == 4 && mahjong.winningTile == tile) {
					nineWait = 1;
				}
			} else if ((j != 1 && j != 9) && amount >= 1) {
				check++;

				if (amount == 2 && mahjong.winningTile == tile) {
					nineWait = 1;
				}
			}
		}

		// printf("check=%d wait=%d\n", check, nineWait);

		if (check == 9) {
			return (nineWait == 1) ? TWO_YAKUMAN : ONE_YAKUMAN;
		}
	}

	return 0;
}

int32_t isThirteenOrphans(myMahjong mahjong) {
	if (mahjong.tilesAmount[PIN_1] >= 1 && mahjong.tilesAmount[PIN_9] >= 1 &&
		mahjong.tilesAmount[SO_1]  >= 1 && mahjong.tilesAmount[SO_9]  >= 1 &&
		mahjong.tilesAmount[MAN_1] >= 1 && mahjong.tilesAmount[MAN_9] >= 1 &&
		mahjong.tilesAmount[EAST]  >= 1 && mahjong.tilesAmount[SOUTH] >= 1 &&
		mahjong.tilesAmount[WEST]  >= 1 && mahjong.tilesAmount[NORTH] >= 1 &&
		mahjong.tilesAmount[WHITE] >= 1 && mahjong.tilesAmount[GREEN] >= 1 &&
		mahjong.tilesAmount[RED]   >= 1 && mahjong.totalTiles == 14) {
		if (mahjong.tilesAmount[mahjong.winningTile] == 2) {
			return TWO_YAKUMAN;
		}

		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isAllGreen(myMahjong mahjong) {
	int32_t so2   = mahjong.tilesAmount[SO_2];
	int32_t so3   = mahjong.tilesAmount[SO_3];
	int32_t so4   = mahjong.tilesAmount[SO_4];
	int32_t so6   = mahjong.tilesAmount[SO_6];
	int32_t so8   = mahjong.tilesAmount[SO_8];
	int32_t green = mahjong.tilesAmount[GREEN];
	int32_t total = so2 + so3 + so4 + so6 + so8 + green;

	if (total == mahjong.totalTiles) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isAllHonors(myMahjong mahjong) {
	if (amountOfHonors(mahjong) == mahjong.totalTiles) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isAllTerminals(myMahjong mahjong) {
	if (amountOfTerminals(mahjong) == mahjong.totalTiles) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isBigThreeDragons(myMahjong mahjong) {
	int32_t white = mahjong.tilesAmount[WHITE];
	int32_t green = mahjong.tilesAmount[GREEN];
	int32_t red   = mahjong.tilesAmount[RED];

	if (white >= 3 && green >= 3 && red >= 3) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t isFourKans(myMahjong mahjong) {
	if (mahjong.totalTiles == 18) {
		return ONE_YAKUMAN;
	}

	return 0;
}

int32_t handleYaku(myMahjong mahjong) {
	int32_t total = 0;

	// 6 Han

	if (isFlush(mahjong) == SIX_HAN) {
		printYaku(FLUSH);
		total += SIX_HAN;
	}

	// 5 Han

	if (isFlush(mahjong) == FIVE_HAN) {
		printYaku(FLUSH_OPEN);
		total += FIVE_HAN;
	}

	// 3 Han

	if (isHalfFlush(mahjong) == THREE_HAN) {
		printYaku(HALF_FLUSH);
		total += THREE_HAN;
	}

	if (isTerminalInEachSet(mahjong) == THREE_HAN) {
		printYaku(TERMINAL_IN_EACH_SET);
		total += THREE_HAN;
	}

	// 2 Han

	if (isAllTerminalsAndHonors(mahjong) == TWO_HAN) {
		printYaku(ALL_TERMINALS_AND_HONORS);
		total += TWO_HAN;
	}

	if (isAllTriplets(mahjong) == TWO_HAN) {
		printYaku(ALL_TRIPLETS);
		total += TWO_HAN;
	}

	if (isHalfFlush(mahjong) == TWO_HAN) {
		printYaku(HALF_FLUSH_OPEN);
		total += TWO_HAN;
	}

	if (isLittleThreeDragons(mahjong) == TWO_HAN) {
		printYaku(LITTLE_THREE_DRAGONS);
		total += TWO_HAN;
	}

	if (isSevenPairs(mahjong) == TWO_HAN) {
		printYaku(SEVEN_PAIRS);
		total += TWO_HAN;
	}

	if (isStraight(mahjong) == TWO_HAN) {
		printYaku(STRAIGHT);
		total += TWO_HAN;
	}

	if (isTerminalInEachSet(mahjong) == TWO_HAN) {
		printYaku(TERMINAL_IN_EACH_SET_OPEN);
		total += TWO_HAN;
	}

	if (isTerminalOrHonorInEachSet(mahjong) == TWO_HAN) {
		printYaku(TERMINAL_OR_HONOR_IN_EACH_SET);
		total += TWO_HAN;
	}

	if (isThreeColourStraights(mahjong) == TWO_HAN) {
		printYaku(THREE_COLOUR_STRAIGHTS);
		total += TWO_HAN;
	}

	if (isThreeColourTriplets(mahjong) == TWO_HAN) {
		printYaku(THREE_COLOUR_TRIPLETS);
		total += TWO_HAN;
	}

	if (isThreeConcealedTriplets(mahjong) == TWO_HAN) {
		printYaku(THREE_CONCEALED_TRIPLETS);
		total += TWO_HAN;
	}

	if (isThreeKans(mahjong) == TWO_HAN) {
		printYaku(THREE_KANS);
		total += TWO_HAN;
	}

	if (isIdenticalSequences(mahjong) == THREE_HAN) {
		printYaku(TWO_SETS_OF_IDENTICAL_SEQUENCES);
		total += THREE_HAN;
	}

	// 1 Han

	if (isAllSimples(mahjong) == ONE_HAN) {
		printYaku(ALL_SIMPLES);
		total += ONE_HAN;
	}

	if (hasHonerGreen(mahjong) == ONE_HAN) {
		printYaku(HONER_GREEN);
		total += ONE_HAN;
	}

	if (hasHonerPlayerWind(mahjong) == ONE_HAN) {
		printYaku(HONER_PLAYER_WIND);
		total += ONE_HAN;
	}

	if (hasHonerPrevailingWind(mahjong) == ONE_HAN) {
		printYaku(HONER_PREVAILING_WIND);
		total += ONE_HAN;
	}

	if (hasHonerRed(mahjong) == ONE_HAN) {
		printYaku(HONER_RED);
		total += ONE_HAN;
	}

	if (hasHonerWhite(mahjong) == ONE_HAN) {
		printYaku(HONER_WHITE);
		total += ONE_HAN;
	}

	if (hasNoPointsHand(mahjong) == ONE_HAN) {
		printYaku(NO_POINTS_HAND);
		total += ONE_HAN;
	}

	if (isIdenticalSequences(mahjong) == ONE_HAN) {
		printYaku(ONE_SET_OF_IDENTICAL_SEQUENCES);
		total += ONE_HAN;
	}

	if (isStraight(mahjong) == ONE_HAN) {
		printYaku(STRAIGHT_OPEN);
		total += ONE_HAN;
	}

	if (isTerminalOrHonorInEachSet(mahjong) == ONE_HAN) {
		printYaku(TERMINAL_OR_HONOR_IN_EACH_SET_OPEN);
		total += ONE_HAN;
	}

	if (isThreeColourStraights(mahjong) == ONE_HAN) {
		printYaku(THREE_COLOUR_STRAIGHTS_OPEN);
		total += ONE_HAN;
	}

	return total;
}

int32_t isFlush(myMahjong mahjong) {
	for (int32_t i = 0; i < 3; i++) {
		int32_t total = 0;

		for (int32_t j = 1; j <= 9; j++) {
			total += mahjong.tilesAmount[i * 9 + j];
		}

		if (total == mahjong.totalTiles) {
			return (isClosedHand(mahjong)) ? SIX_HAN : FIVE_HAN;
		}
	}

	return 0;
}

int32_t isHalfFlush(myMahjong mahjong) {
	if (amountOfHonors(mahjong) == 0) {
		return 0;
	}

	for (int32_t i = 0; i < 3; i++) {
		int32_t totalSuits = 0;

		for (int32_t j = 1; j <= 9; j++) {
			totalSuits += mahjong.tilesAmount[i * 9 + j];
		}

		if ((totalSuits + amountOfHonors(mahjong)) == mahjong.totalTiles) {
			return (isClosedHand(mahjong)) ? THREE_HAN : TWO_HAN;
		}
	}

	return 0;
}

int32_t isTerminalInEachSet(myMahjong mahjong) {
	if (amountOfHonors(mahjong) != 0) {
		return 0;
	}

	int32_t check = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];

		for (int32_t j = head; j < tail; j++) {
			if (isYaochuTile(mahjong.tiles[j])) {
				check++;
				break;
			}
		}
	}

	if (isYaochuTile(mahjong.tiles[mahjong.totalTiles-1])) {
		check++;
	}

	if (check == 5) {
		return (isClosedHand(mahjong)) ? THREE_HAN : TWO_HAN;
	}

	return 0;
}

int32_t isAllTerminalsAndHonors(myMahjong mahjong) {
	int32_t honors = amountOfHonors(mahjong);
	int32_t terminals = amountOfTerminals(mahjong);

	if (honors == 0 || terminals == 0) {
		return 0;
	}

	if (honors + terminals == mahjong.totalTiles) {
		return TWO_HAN;
	}

	return 0;
}

int32_t isAllTriplets(myMahjong mahjong) {
	int32_t triplet = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (isTripletOrKanMeld(mahjong, i)) {
			triplet++;
		}
	}

	if (triplet == 4) {
		return TWO_HAN;
		// return (pair == 1) ? TWO_YAKUMAN : ONE_YAKUMAN;
	}

	return 0;
}

int32_t isLittleThreeDragons(myMahjong mahjong) {
	int32_t triplet = 0, pair = 0;

	for (int32_t i = WHITE; i <= RED; i++) {
		if (mahjong.tilesAmount[i] >= 3) {
			triplet++;
		} else if (mahjong.tilesAmount[i] == 2) {
			pair = 1;
		}
	}

	if (triplet == 2 && pair == 1) {
		return TWO_HAN;
	}

	return 0;
}

int32_t isSevenPairs(myMahjong mahjong) {
	int32_t pair = 0;

	for (int32_t i = 1; i <= TILE_TYPE; i++) {
		if (mahjong.tilesAmount[i] == 2) {
			pair++;
		} else if (mahjong.tilesAmount[i] != 0) {
			return 0;
		}
	}

	if (pair == 7 && mahjong.totalMelds != 4) {
		return TWO_HAN;
	}

	return 0;
}

int32_t isStraight(myMahjong mahjong) {
	int32_t check123[3] = {0}, check456[3] = {0}, check789[3] = {0};

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isStraightMeld(mahjong, i)) {
			continue;
		}

		// printf("is straight!\n");

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];
		int32_t check[9] = {0};

		for (int32_t j = head; j < tail; j++) {
			int32_t num  = (mahjong.tiles[j] - 1) % 9;
			int32_t type = (mahjong.tiles[j] - 1) / 9 + 1;

			check[num] = type;
		}

		// printf("check: ");
		// for(int32_t j = 0; j < 9; j++) {
		// 	printf("%d ", check[j]);
		// }
		// printf("\n");

		if (check[0] && (check[0] == check[1]) && (check[0] == check[2])) {
			check123[check[0] - 1]++;
		}

		if (check[3] && (check[3] == check[4]) && (check[3] == check[5])) {
			check456[check[3] - 1]++;
		}

		if (check[6] && (check[6] == check[7]) && (check[6] == check[8])) {
			check789[check[6] - 1]++;
		}
	}

	// for (int32_t i = 0; i < 3; i++) {
	// 	printf("i=%d: %d %d %d\n", i+1, check123[i], check456[i], check789[i]);
	// }

	if ((check123[0] && check456[0] && check789[0]) ||
		(check123[1] && check456[1] && check789[1]) ||
		(check123[2] && check456[2] && check789[2])) {
		return (isClosedHand(mahjong)) ? TWO_HAN : ONE_HAN;
	}

	return 0;
}

int32_t isTerminalOrHonorInEachSet(myMahjong mahjong) {
	if (amountOfHonors(mahjong) == 0) {
		return 0;
	}

	int32_t straight = 0, yaochu = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (isStraightMeld(mahjong, i)) {
			straight++;
		}

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];

		for (int32_t i = head; i < tail; i++) {
			if (isYaochuTile(mahjong.tiles[i])) {
				yaochu++;
				break;
			}
		}
	}

	if (isYaochuTile(mahjong.tiles[mahjong.totalTiles-1])) {
		yaochu++;
	}

	if (straight && (yaochu == mahjong.totalMelds + 1)) {
		return (isClosedHand(mahjong)) ? TWO_HAN : ONE_HAN;
	}

	return 0;
}

int32_t isThreeColourStraights(myMahjong mahjong) {
	int32_t result[7][3] = {0};

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isStraightMeld(mahjong, i)) {
			continue;
		}

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];
		int32_t check[9] = {0};

		for (int32_t j = head; j < tail; j++) {
			int32_t num  = (mahjong.tiles[j] - 1) % 9;
			int32_t type = (mahjong.tiles[j] - 1) / 9 + 1;
			check[num] = type;
		}

		for (int32_t j = 0; j < 7; j++) {
			if (check[j] && (check[j] == check[j+1]) && (check[j] == check[j+2])) {
				result[j][check[j] - 1]++;
			}
		}
	}

	// printf("     P S M\n");
	// for (int32_t i = 0; i < 7; i++) {
	// 	printf("%d%d%d: ", i+1,i+2,i+3);
	// 	for (int32_t j = 0; j < 3; j++) {
	// 		printf("%d ", result[i][j]);
	// 	}
	// 	printf("\n");
	// }

	for (int32_t i = 0; i < 7; i++) {
		if (result[i][0] && result[i][1] && result[i][2]) {
			return (isClosedHand(mahjong)) ? TWO_HAN : ONE_HAN;
		}
	}

	return 0;
}

int32_t isThreeColourTriplets(myMahjong mahjong) {
	int32_t result[9][3] = {0};

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isTripletOrKanMeld(mahjong, i)) {
			continue;
		}

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tile = mahjong.tiles[head];

		if (isHonorTile(tile)) {
			continue;
		}

		result[(tile - 1) % 9][(tile - 1) / 9]++;
	}

	// printf("   P S M\n");
	// for (int32_t i = 0; i < 9; i++) {
	// 	printf("%d: ", i+1);
	// 	for (int32_t j = 0; j < 3; j++) {
	// 		printf("%d ", result[i][j]);
	// 	}
	// 	printf("\n");
	// }

	for (int32_t i = 0; i < 9; i++) {
		if (result[i][0] && result[i][1] && result[i][2]) {
			return TWO_HAN;
		}
	}

	return 0;
}

int32_t isThreeConcealedTriplets(myMahjong mahjong) {
	int32_t close = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isTripletOrKanMeld(mahjong, i)) {
			continue;
		}

		if (mahjong.melds[i][MELD_OPEN] == 0) {
			close++;
		}
	}

	if (close == 3) {
		return TWO_HAN;
	}

	return 0;
}

int32_t isThreeKans(myMahjong mahjong) {
	if (mahjong.totalTiles == 17) {
		return TWO_HAN;
	}

	return 0;
}

int32_t isIdenticalSequences(myMahjong mahjong) {
	if (!isClosedHand(mahjong)) {
		return 0;
	}

	int32_t result[7][3] = {0};
	
	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isStraightMeld(mahjong, i)) {
			continue;
		}

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];
		int32_t check[9] = {0};

		for (int32_t j = head; j < tail; j++) {
			int32_t num  = (mahjong.tiles[j] - 1) % 9;
			int32_t type = (mahjong.tiles[j] - 1) / 9 + 1;
			check[num] = type;
		}

		for (int32_t j = 0; j < 7; j++) {
			if (check[j] && (check[j] == check[j+1]) && (check[j] == check[j+2])) {
				result[j][check[j] - 1]++;
			}
		}
	}

	int32_t identical = 0;

	for (int32_t i = 0; i < 7; i++) {
		for (int32_t j = 0; j < 3; j++) {
			if (result[i][j] == 2) {
				identical++;
			}
		}
	}

	if (identical == 2) {
		return THREE_HAN;
	} else if (identical == 1) {
		return ONE_HAN;
	}

	return 0;
}

int32_t isAllSimples(myMahjong mahjong) {
	for (int32_t i = 0; i < mahjong.totalTiles; i++) {
		if (isYaochuTile(mahjong.tiles[i])) {
			return 0;
		}
	}

	return ONE_HAN;
}

int32_t hasHonerGreen(myMahjong mahjong) {
	if (mahjong.tilesAmount[GREEN] >= 3) {
		return ONE_HAN;
	}

	return 0;
}

int32_t hasHonerPlayerWind(myMahjong mahjong) {
	for (int32_t i = EAST; i <= NORTH; i++) {
		if (mahjong.tilesAmount[i] >= 3 && (mahjong.playerWind + EAST == i)) {
			return ONE_HAN;
		}
	}

	return 0;
}

int32_t hasHonerPrevailingWind(myMahjong mahjong) {
	for (int32_t i = EAST; i <= NORTH; i++) {
		if (mahjong.tilesAmount[i] >= 3 && (mahjong.prevailingWind + EAST == i)) {
			return ONE_HAN;
		}
	}

	return 0;
}

int32_t hasHonerRed(myMahjong mahjong) {
	if (mahjong.tilesAmount[RED] >= 3) {
		return ONE_HAN;
	}

	return 0;
}

int32_t hasHonerWhite(myMahjong mahjong) {
	if (mahjong.tilesAmount[WHITE] >= 3) {
		return ONE_HAN;
	}

	return 0;
}

int32_t hasNoPointsHand(myMahjong mahjong) {
	if (!isClosedHand(mahjong)) {
		return 0;
	}

	int32_t noPointsHand = 0;

	for (int32_t i = 0; i < mahjong.totalMelds; i++) {
		if (!isStraightMeld(mahjong, i)) {
			return 0;
		}

		int32_t head = (i == 0) ? 0 : mahjong.melds[i-1][MELD_TILES];
		int32_t tail = mahjong.melds[i][MELD_TILES];
		int32_t check[9] = {0};

		for (int32_t j = head; j < tail; j++) {
			int32_t num = (mahjong.tiles[j] - 1) % 9;
			check[num] = mahjong.tiles[j];
		}

		for (int32_t j = 0; j < 7; j++) {
			if ((check[j] && check[j+1] == mahjong.winningTile) ||
				(j == 6 && check[j] == mahjong.winningTile) ||
				(j == 0 && check[j+2] == mahjong.winningTile)) {
				break;
			} else if (check[j] == mahjong.winningTile || 
					(check[j] && check[j+2] == mahjong.winningTile)) {
				noPointsHand++;
				break;
			}
		}
	}

	if (noPointsHand) {
		return ONE_HAN;
	}

	return 0;
}

void printYaku(int32_t yaku) {
	printf("    ");

	switch (yaku) {
		// Two Yakuman

		case BIG_FOUR_WINDS:
		printf("Big four winds (2 Yakuman)\n"); break;

		case FOUR_CONCEALED_TRIPLETS_SINGLE_WAIT:
		printf("Four concealed triplets single wait (2 Yakuman)\n"); break;

		case NINE_GATES_NINE_WAIT:
		printf("Nine gates nine wait (2 Yakuman)\n"); break;

		case THIRTEEN_ORPHANS_13_WAIT:
		printf("Thirteen orphans 13 wait (2 Yakuman)\n"); break;

		// One Yakuman

		case ALL_GREEN:
		printf("All green (1 Yakuman)\n"); break;

		case ALL_HONORS:
		printf("All honors (1 Yakuman)\n"); break;

		case ALL_TERMINALS:
		printf("All terminals (1 Yakuman)\n"); break;

		case BIG_THREE_DRAGONS:
		printf("Big three dragons (1 Yakuman)\n"); break;

		case FOUR_CONCEALED_TRIPLETS:
		printf("Four concealed triplets (1 Yakuman)\n"); break;

		case FOUR_KANS:
		printf("Four kans (1 Yakuman)\n"); break;

		case LITTLE_FOUR_WINDS:
		printf("Little four winds (1 Yakuman)\n"); break;

		case NINE_GATES:
		printf("Nine gates (1 Yakuman)\n"); break;

		case THIRTEEN_ORPHANS:
		printf("Thirteen orphans (1 Yakuman)\n"); break;

		// 6 Han

		case FLUSH:
		printf("Flush (6 Han)\n"); break;

		// 5 Han

		case FLUSH_OPEN:
		printf("Flush (5 Han)\n"); break;

		// 3 Han

		case HALF_FLUSH:
		printf("Half-flush (3 Han)\n"); break;

		case TERMINAL_IN_EACH_SET:
		printf("Terminal in each set (3 Han)\n"); break;

		case TWO_SETS_OF_IDENTICAL_SEQUENCES:
		printf("Two sets of identical sequences (3 Han)\n"); break;

		// 2 Han

		case ALL_TERMINALS_AND_HONORS:
		printf("All terminals and honors (2 Han)\n"); break;

		case ALL_TRIPLETS:
		printf("All triplets (2 Han)\n"); break;

		case HALF_FLUSH_OPEN:
		printf("Half-flush (2 Han)\n"); break;

		case LITTLE_THREE_DRAGONS:
		printf("Little three dragons (2 Han)\n"); break;

		case SEVEN_PAIRS:
		printf("Seven pairs (2 Han)\n"); break;

		case STRAIGHT:
		printf("Straight (2 Han)\n"); break;

		case TERMINAL_IN_EACH_SET_OPEN:
		printf("Terminal in each set (2 Han)\n"); break;

		case TERMINAL_OR_HONOR_IN_EACH_SET:
		printf("Terminal or honor in each set (2 Han)\n"); break;

		case THREE_COLOUR_STRAIGHTS:
		printf("Three colour straights (2 Han)\n"); break;

		case THREE_COLOUR_TRIPLETS:
		printf("Three colour triplets (2 Han)\n"); break;

		case THREE_CONCEALED_TRIPLETS:
		printf("Three concealed triplets (2 Han)\n"); break;

		case THREE_KANS:
		printf("Three kans (2 Han)\n"); break;

		// 1 Han

		case ALL_SIMPLES:
		printf("All simples (1 Han)\n"); break;

		case HONER_GREEN:
		printf("Honer: Green (1 Han)\n"); break;

		case HONER_PLAYER_WIND:
		printf("Honer: Player's wind (1 Han)\n"); break;

		case HONER_PREVAILING_WIND:
		printf("Honer: Prevailing wind (1 Han)\n"); break;

		case HONER_RED:
		printf("Honer: Red (1 Han)\n"); break;

		case HONER_WHITE:
		printf("Honer: White (1 Han)\n"); break;

		case NO_POINTS_HAND:
		printf("No-points Hand (1 Han)\n"); break;

		case ONE_SET_OF_IDENTICAL_SEQUENCES:
		printf("One set of identical sequences (1 Han)\n"); break;

		case STRAIGHT_OPEN:
		printf("Straight (1 Han)\n"); break;

		case TERMINAL_OR_HONOR_IN_EACH_SET_OPEN:
		printf("Terminal or honor in each set (1 Han)\n"); break;

		case THREE_COLOUR_STRAIGHTS_OPEN:
		printf("Three colour straights (1 Han)\n"); break;

		case NO_YAKU:
		printf("No Yaku\n"); break;

		// Error

		case ERROR_YAKU:
		default: 
		printf("Unreasonable case\n"); break;
	}
}

```
:::

## 4.6 What Happens?
