Example #1
0
func (t *testSuite) TestBidding() {
	// 9D 9D QD TD TD AD JC QC KC AH AH KS
	hand := sdz.Hand{C("9D"), C("9D"), C("QD"), C("TD"), C("TD"), C("AD"), C("JC"), C("QC"), C("KC"), C("AH"), C("AH"), C("KS")}
	sort.Sort(hand)
	ai := createAI()
	ai.SetHand(hand, 0, 1)
	go ai.Go()
	ai.Tell(sdz.CreateBid(0, 1))
	action, _ := ai.Listen()
	t.Not(t.True(22 > action.Bid || action.Bid > 24))
}
Example #2
0
func (ai *AI) Go() {
	for {
		action, open := ai.Listen()
		//Log("Action received by player %d with hand %s - %+v", ai.Playerid(), ai.hand, action)
		if !open {
			return
		}
		switch action.Type {
		case "Bid":
			if action.Playerid == ai.Playerid() {
				Log("------------------Player %d asked to bid against player %d", ai.Playerid(), ai.highBidder)
				ai.bidAmount, ai.trump, ai.show = ai.calculateBid()
				if ai.numBidders == 1 && ai.IsPartner(ai.highBidder) && ai.bidAmount < 21 && ai.bidAmount+5 > 20 {
					// save our parter
					Log("Saving our partner with a recommended bid of %d", ai.bidAmount)
					ai.bidAmount = 21
				}
				bidAmountOld := ai.bidAmount
				switch {
				case ai.Playerid() == ai.highBidder: // this should only happen if I was the dealer and I got stuck
					ai.bidAmount = 20
				case ai.highBid > ai.bidAmount:
					ai.bidAmount = 0
				case ai.highBid == ai.bidAmount && !ai.IsPartner(ai.highBidder): // if equal with an opponent, bid one over them for spite!
					ai.bidAmount++
				case ai.numBidders == 3: // I'm last to bid, but I want it
					ai.bidAmount = ai.highBid + 1
				}
				meld, _ := ai.hand.Meld(ai.trump)
				Log("------------------Player %d bid %d over %d with recommendation of %d and %d meld", ai.Playerid(), ai.bidAmount, ai.highBid, bidAmountOld, meld)
				ai.c <- sdz.CreateBid(ai.bidAmount, ai.Playerid())
			} else {
				// received someone else's bid value'
				if ai.highBid < action.Bid {
					ai.highBid = action.Bid
					ai.highBidder = action.Playerid
				}
				ai.numBidders++
			}
		case "Play":
			if action.Playerid == ai.Playerid() {
				decisionMap := make(map[sdz.Card]int)
				var selection sdz.Card
				for _, card := range *ai.hand {
					if ai.playCount == 0 || sdz.ValidPlay(card, action.WinningCard, action.Lead, ai.hand, action.Trump) {
						decisionMap[card] = 1
						selection = card
					}
				}
				for card := range decisionMap {
					if ai.playCount == 0 {
						// TODO: Anticipate opponents trumping in
						if card.Face() == sdz.Ace {
							// choose the Ace with the least amount of cards in the suit
							decisionMap[card] += 12 - ai.hand.CountSuit(card.Suit())
						}
					} else if card.Beats(action.WinningCard, action.Trump) {
						if ai.hand.Highest(card) {
							decisionMap[card]++
						}
					} else if ai.playCount > 0 && action.WinningPlayer%2 == ai.Playerid()%2 {
						if card.Counter() {
							decisionMap[card]++
						} else {
							decisionMap[card]--
						}
					} else {
						// TODO: Anticipate partner winning the hand through trump or otherwise
						if ai.hand.Lowest(card) {
							decisionMap[card]++
						}
					}
					if decisionMap[card] > decisionMap[selection] {
						selection = card
					}
				}
				Log("%d - Playing %s - Decision map = %v", ai.Playerid(), selection, decisionMap)
				action = sdz.CreatePlay(selection, ai.Playerid())
				ai.ht.playedCards[action.PlayedCard]++
				ai.c <- action
			} else {
				ai.playCount++
				ai.ht.playedCards[action.PlayedCard]++
				// TODO: Keep track of what has been played already
				// received someone else's play
			}
		case "Trump":
			if action.Playerid == ai.Playerid() {
				meld, _ := ai.hand.Meld(ai.trump)
				Log("Player %d being asked to name trump on hand %s and have %d meld", ai.Playerid(), ai.hand, meld)
				switch {
				// TODO add case for the end of the game like if opponents will coast out
				case ai.bidAmount < 15:
					ai.c <- sdz.CreateThrowin(ai.Playerid())
				default:
					ai.c <- sdz.CreateTrump(ai.trump, ai.Playerid())
				}
			} else {
				//Log("Player %d was told trump", ai.Playerid())
				ai.trump = action.Trump
			}
		case "Throwin":
			Log("Player %d saw that player %d threw in", ai.Playerid(), action.Playerid)
		case "Deal": // nothing to do here, this is set automagically
		case "Meld": // nothing to do here, no one to read it
		case "Message": // nothing to do here, no one to read it
		case "Trick": // nothing to do here, nothing to display
			ai.playCount = 0
		case "Score": // TODO: save score to use for future bidding techniques
		default:
			Log("Received an action I didn't understand - %v", action)
		}
	}
}
Example #3
0
func main() {
	autoClient := false
	for _, s := range os.Args {
		fmt.Println(s)
		if s == "auto" {
			autoClient = true
		}
	}
	conn, err := websocket.Dial("ws://localhost:10080/connect", "", "http://localhost:10080/")
	var playerid int
	var hand *sdz.Hand
	var bidAmount int
	var trump sdz.Suit
	if err != nil {
		sdz.Log("Error - %v", err)
		return
	}
	defer conn.Close()
	var previousPlay *sdz.Action
	var previousCard sdz.Card
	for {
		var action sdz.Action
		err := websocket.JSON.Receive(conn, &action)
		if err != nil {
			sdz.Log("Error decoding - %v", err)
			return
		}
		switch action.Type {
		case "Bid":
			if action.Playerid == playerid {
				sdz.Log("How much would you like to bid?:")
				fmt.Scan(&bidAmount)
				send(conn, sdz.CreateBid(bidAmount, playerid))
			} else {
				// received someone else's bid value'
				sdz.Log("Player #%d bid %d", action.Playerid, action.Bid)
			}
		case "Play":
			if action.Playerid == playerid {
				if previousPlay == nil || action.Lead == "" {
					previousPlay = &action
				} else {
					sdz.Log("Server rejected the play of %s, invalid play", previousCard)
					*hand = append(*hand, previousCard)
					sort.Sort(hand)
				}
				var card sdz.Card
				if action.Lead == "" {
					card = (*hand)[0]
				} else {
					for _, c := range *hand {
						if sdz.ValidPlay(c, action.WinningCard, action.Lead, hand, trump) {
							card = c
						}
					}
				}
				sdz.Log("Your turn, in your hand is %s - what would you like to play? Trump is %s - valid play is %s:", hand, trump, card)
				for {
					if !autoClient {
						fmt.Scan(&card)
					}
					//sdz.Log("Received input %s", card)
					if hand.Remove(card) {
						send(conn, sdz.CreatePlay(card, playerid))
						previousCard = card
						break
					} else {
						sdz.Log("Invalid play, card does not exist in your hand")
					}
				}
			} else {
				sdz.Log("Player %d played card %s", action.Playerid, action.PlayedCard)
				previousPlay = nil // not going to ask us to replay since the next response was another player's play
				// received someone else's play'
			}
		case "Trump":
			if action.Playerid == playerid {
				sdz.Log("What would you like to make trump?")
				fmt.Scan(&trump)
				send(conn, sdz.CreateTrump(trump, playerid))
			} else {
				sdz.Log("Player %d says trump is %s", action.Playerid, action.Trump)
				trump = action.Trump
			}
		case "Throwin":
			sdz.Log("Player %d threw in", action.Playerid)
		case "Deal":
			playerid = action.Playerid
			hand = &action.Hand
			sdz.Log("Your hand is - %s", hand)
		case "Meld":
			sdz.Log("Player %d is melding %s for %d points", action.Playerid, action.Hand, action.Amount)
		case "Score": // this client does not have to implement this type as it's already told through Message actions
		case "Message":
			sdz.Log(action.Message)
		case "Hello":
			var response string
			fmt.Scan(&response)
			send(conn, sdz.CreateHello(response))
		case "Game":
			var option int
			fmt.Scan(&option)
			send(conn, sdz.CreateGame(option))
		default:
			sdz.Log("Received an action I didn't understand - %v", action)
		}

	}
}