diff --git a/src/game/rule/operation/hand.go b/src/game/rule/operation/hand.go index 223337e..16b9e35 100644 --- a/src/game/rule/operation/hand.go +++ b/src/game/rule/operation/hand.go @@ -5,7 +5,7 @@ import ( "sort" ) -func royalFlush(game *entity.Game, _ interface{}) int { +func royalFlush(game *entity.Game, _ interface{}) uint64 { hand := getHand(game) if !hand.Flush() || !hand.Straight() { return 0 @@ -18,7 +18,7 @@ func royalFlush(game *entity.Game, _ interface{}) int { return 1 } -func straightFlush(game *entity.Game, _ interface{}) int { +func straightFlush(game *entity.Game, _ interface{}) uint64 { hand := getHand(game) if !hand.Flush() || !hand.Straight() { return 0 @@ -29,29 +29,14 @@ func straightFlush(game *entity.Game, _ interface{}) int { biggest = card.Value } } - return biggest + return uint64(biggest) } -func fourOfAKind(game *entity.Game, _ interface{}) int { - hand := getHand(game) - counts := counts(hand) - best := entity.Card{} - high := entity.Card{} - for k, v := range counts { - if v >= 4 && k.Value > best.Value { - best = k - } - if v != 4 && k.Value > high.Value { - high = k - } - } - if best.Value == 0 { - return 0 - } - return best.Value*100 + high.Value +func fourOfAKind(game *entity.Game, _ interface{}) uint64 { + return nOfAKind(game, 4) } -func fullHouse(game *entity.Game, _ interface{}) int { +func fullHouse(game *entity.Game, _ interface{}) uint64 { hand := getHand(game) counts := counts(hand) trio := entity.Card{} @@ -67,27 +52,18 @@ func fullHouse(game *entity.Game, _ interface{}) int { if trio.Value == 0 || duo.Value == 0 { return 0 } - return trio.Value*100 + duo.Value + return uint64(trio.Value*100 + duo.Value) } -func flush(game *entity.Game, _ interface{}) int { +func flush(game *entity.Game, _ interface{}) uint64 { hand := getHand(game) if !hand.Flush() { return 0 } - values := make([]int, 0) - for _, card := range hand.AllCards() { - values = append(values, card.Value) - } - sort.Ints(values) - rank := 0 - for i := len(values) - 1; i >= 0; i-- { - rank = rank*100 + values[i] - } - return rank + return highCard(game, nil) } -func straight(game *entity.Game, _ interface{}) int { +func straight(game *entity.Game, _ interface{}) uint64 { hand := getHand(game) if !hand.Straight() { return 0 @@ -98,23 +74,76 @@ func straight(game *entity.Game, _ interface{}) int { big = card.Value } } - return big + return uint64(big) } -func threeOfAKind(game *entity.Game, _ interface{}) int { - panic("not impl") +func threeOfAKind(game *entity.Game, _ interface{}) uint64 { + return nOfAKind(game, 3) } -func twoPair(game *entity.Game, _ interface{}) int { - panic("not impl") +func twoPair(game *entity.Game, _ interface{}) uint64 { + high := nOfAKind(game, 2) + if high == 0 { + return 0 + } + high = high / 100 + hand := getHand(game) + counts := counts(hand) + low := 0 + highCard := 0 + for k, v := range counts { + if ((uint64(k.Value) != high && v >= 2) || v >= 4) && k.Value > low { + low = k.Value + } + } + if low == 0 { + return 0 + } + for k, v := range counts { + if ((uint64(k.Value) != high && k.Value != low) || v > 4 || v == 3) && k.Value > highCard { + highCard = k.Value + } + } + return high*100*100 + uint64(low*100+highCard) } -func pair(game *entity.Game, _ interface{}) int { - panic("not impl") +func pair(game *entity.Game, _ interface{}) uint64 { + return nOfAKind(game, 2) } -func highCard(game *entity.Game, _ interface{}) int { - panic("not impl") +func nOfAKind(game *entity.Game, n int) uint64 { + hand := getHand(game) + counts := counts(hand) + best := entity.Card{} + high := entity.Card{} + for i := 0; i < 2; i++ { + for k, v := range counts { + if v >= n && k.Value > best.Value { + best = k + } + if (v != n || k.Value != best.Value) && k.Value > high.Value { + high = k + } + } + } + if best.Value == 0 { + return 0 + } + return uint64(best.Value*100 + high.Value) +} + +func highCard(game *entity.Game, _ interface{}) uint64 { + hand := getHand(game) + values := make([]int, 0) + for _, card := range hand.AllCards() { + values = append(values, card.Value) + } + sort.Ints(values) + value := uint64(0) + for i := len(values) - 1; i >= 0; i-- { + value = value*100 + uint64(values[i]) + } + return value } func getHand(game *entity.Game) entity.Hand { diff --git a/src/game/rule/operation/hand_test.go b/src/game/rule/operation/hand_test.go index 60d8212..e003920 100644 --- a/src/game/rule/operation/hand_test.go +++ b/src/game/rule/operation/hand_test.go @@ -102,6 +102,123 @@ func TestFlush(t *testing.T) { } } +func TestHighCard(t *testing.T) { + cases := map[string]testHandCase{ + "no cards": { + want: 0, + }, + "seven card": { + public: []entity.Card{ + entity.Card{Value: 13}, + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 3}, + entity.Card{Value: 4}, + }, + want: 13111111110403, + }, + "four card": { + public: []entity.Card{ + entity.Card{Value: 13}, + entity.Card{Value: 11}, + entity.Card{Value: 3}, + entity.Card{Value: 4}, + }, + want: 13110403, + }, + "three card": { + public: []entity.Card{ + entity.Card{Value: 13}, + entity.Card{Value: 3}, + entity.Card{Value: 4}, + }, + want: 130403, + }, + "two card": { + public: []entity.Card{ + entity.Card{Value: 3}, + entity.Card{Value: 4}, + }, + want: 403, + }, + "one card": { + public: []entity.Card{ + entity.Card{Value: 3}, + }, + want: 3, + }, + } + + for name, d := range cases { + testHand(t, name, highCard, d.public, d.private, d.want) + } +} + +func TestTwoPair(t *testing.T) { + cases := map[string]testHandCase{ + "no cards": { + want: 0, + }, + "no pair": { + public: []entity.Card{ + entity.Card{Value: 11}, + entity.Card{Value: 10}, + }, + want: 0, + }, + "one pair": { + public: []entity.Card{ + entity.Card{Value: 11}, + entity.Card{Value: 11}, + }, + want: 0, + }, + "no second pair": { + public: []entity.Card{ + entity.Card{Value: 12}, + entity.Card{Value: 12}, + entity.Card{Value: 11}, + entity.Card{Value: 10}, + }, + want: 0, + }, + "two pair diff": { + public: []entity.Card{ + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 10}, + entity.Card{Value: 10}, + }, + want: 111000, + }, + "two pair same": { + public: []entity.Card{ + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 11}, + }, + want: 111100, + }, + "two pair high": { + public: []entity.Card{ + entity.Card{Value: 11}, + entity.Card{Value: 11}, + entity.Card{Value: 10}, + entity.Card{Value: 10}, + entity.Card{Value: 13}, + }, + want: 111013, + }, + } + + for name, d := range cases { + testHand(t, name, twoPair, d.public, d.private, d.want) + } +} + func TestFullHouse(t *testing.T) { cases := map[string]testHandCase{ "no cards": { @@ -144,8 +261,8 @@ func TestFullHouse(t *testing.T) { } } -func TestFourOfAKind(t *testing.T) { - cases := map[string]testHandCase{ +func TestNOfAKind(t *testing.T) { + cases4 := map[string]testHandCase{ "no cards": { want: 0, }, @@ -191,9 +308,118 @@ func TestFourOfAKind(t *testing.T) { }, } - for name, d := range cases { + for name, d := range cases4 { testHand(t, name, fourOfAKind, d.public, d.private, d.want) } + + cases2 := map[string]testHandCase{ + "no cards": { + want: 0, + }, + "one card": { + public: []entity.Card{ + entity.Card{Value: 5}, + }, + want: 0, + }, + "two cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 500, + }, + "three cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 505, + }, + "four cards, two diff pairs": { + public: []entity.Card{ + entity.Card{Value: 4}, + entity.Card{Value: 4}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 504, + }, + "four cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 505, + }, + "five cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 505, + }, + } + + for name, d := range cases2 { + testHand(t, name, pair, d.public, d.private, d.want) + } + + cases3 := map[string]testHandCase{ + "no cards": { + want: 0, + }, + "one card": { + public: []entity.Card{ + entity.Card{Value: 5}, + }, + want: 0, + }, + "two cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 0, + }, + "three cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 500, + }, + "four cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 505, + }, + "five cards": { + public: []entity.Card{ + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + entity.Card{Value: 5}, + }, + want: 505, + }, + } + + for name, d := range cases3 { + testHand(t, name, threeOfAKind, d.public, d.private, d.want) + } } func TestStraightFlush(t *testing.T) { @@ -272,7 +498,7 @@ func testHand(t *testing.T, name string, foo Int, public []entity.Card, private }, } got := foo(game, nil) - if got != want { + if got != uint64(want) { t.Fatal(want, got) } }) diff --git a/src/game/rule/operation/int.go b/src/game/rule/operation/int.go index 99e20aa..77b3014 100644 --- a/src/game/rule/operation/int.go +++ b/src/game/rule/operation/int.go @@ -6,7 +6,7 @@ import ( "local/sandbox/cards/src/entity" ) -type Int func(*entity.Game, interface{}) int +type Int func(*entity.Game, interface{}) uint64 var intStringified = map[string]Int{ "royalFlush": royalFlush, diff --git a/src/game/rule/operation/operation_test.go b/src/game/rule/operation/operation_test.go index 5ecad98..159123c 100644 --- a/src/game/rule/operation/operation_test.go +++ b/src/game/rule/operation/operation_test.go @@ -6,7 +6,7 @@ import ( ) func TestOperationInterface(t *testing.T) { - foo := func(*entity.Game, interface{}) int { return 0 } + foo := func(*entity.Game, interface{}) uint64 { return 0 } var _ Int = foo bar := func(*entity.Game, interface{}) bool { return false } var _ Bool = bar