Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 1 | package impl |
| 2 | |
| 3 | import ( |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 4 | "io" |
| 5 | "math/rand" |
| 6 | "sync" |
| 7 | "time" |
| 8 | |
| 9 | rps "veyron/examples/rockpaperscissors" |
| 10 | "veyron/examples/rockpaperscissors/common" |
| 11 | |
| 12 | "veyron2" |
| 13 | "veyron2/naming" |
| 14 | "veyron2/vlog" |
| 15 | ) |
| 16 | |
| 17 | type Player struct { |
| 18 | mt naming.MountTable |
| 19 | lock sync.Mutex |
| 20 | gamesPlayed common.Counter |
| 21 | gamesWon common.Counter |
| 22 | } |
| 23 | |
| 24 | func NewPlayer(mt naming.MountTable) *Player { |
| 25 | return &Player{mt: mt} |
| 26 | } |
| 27 | |
| 28 | func (p *Player) Stats() (played, won int64) { |
| 29 | played = p.gamesPlayed.Value() |
| 30 | won = p.gamesWon.Value() |
| 31 | return |
| 32 | } |
| 33 | |
| 34 | func (p *Player) InitiateGame() error { |
| 35 | judge, err := common.FindJudge(p.mt) |
| 36 | if err != nil { |
| 37 | vlog.Infof("FindJudge: %v", err) |
| 38 | return err |
| 39 | } |
| 40 | gameID, err := p.createGame(judge) |
| 41 | if err != nil { |
| 42 | vlog.Infof("createGame: %v", err) |
| 43 | return err |
| 44 | } |
| 45 | vlog.Infof("Created gameID %q on %q", gameID, judge) |
| 46 | |
| 47 | opponent, err := common.FindPlayer(p.mt) |
| 48 | if err != nil { |
| 49 | vlog.Infof("FindPlayer: %v", err) |
| 50 | return err |
| 51 | } |
| 52 | vlog.Infof("chosen opponent is %q", opponent) |
Robin Thellend | 912059e | 2014-05-31 18:26:11 -0700 | [diff] [blame^] | 53 | if err = p.sendChallenge(opponent, judge, gameID); err != nil { |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 54 | vlog.Infof("sendChallenge: %v", err) |
| 55 | return err |
| 56 | } |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 57 | result, err := p.playGame(judge, gameID) |
| 58 | if err != nil { |
| 59 | vlog.Infof("playGame: %v", err) |
| 60 | return err |
| 61 | } |
| 62 | if result.YouWon { |
| 63 | vlog.Info("Game result: I won! :)") |
| 64 | } else { |
| 65 | vlog.Info("Game result: I lost :(") |
| 66 | } |
| 67 | return nil |
| 68 | } |
| 69 | |
| 70 | func (p *Player) createGame(server string) (rps.GameID, error) { |
| 71 | j, err := rps.BindRockPaperScissors(server) |
| 72 | if err != nil { |
| 73 | return rps.GameID{}, err |
| 74 | } |
| 75 | numRounds := 3 + rand.Intn(3) |
| 76 | gameType := rps.Classic |
| 77 | if rand.Intn(2) == 1 { |
| 78 | gameType = rps.LizardSpock |
| 79 | } |
| 80 | return j.CreateGame(rps.GameOptions{NumRounds: int32(numRounds), GameType: gameType}) |
| 81 | } |
| 82 | |
Robin Thellend | 912059e | 2014-05-31 18:26:11 -0700 | [diff] [blame^] | 83 | func (p *Player) sendChallenge(opponent, judge string, gameID rps.GameID) error { |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 84 | o, err := rps.BindRockPaperScissors(opponent) |
| 85 | if err != nil { |
Robin Thellend | 912059e | 2014-05-31 18:26:11 -0700 | [diff] [blame^] | 86 | return err |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 87 | } |
| 88 | return o.Challenge(judge, gameID) |
| 89 | } |
| 90 | |
| 91 | // challenge receives an incoming challenge. |
Robin Thellend | 912059e | 2014-05-31 18:26:11 -0700 | [diff] [blame^] | 92 | func (p *Player) challenge(judge string, gameID rps.GameID) error { |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 93 | vlog.Infof("challenge received: %s %v", judge, gameID) |
| 94 | go p.playGame(judge, gameID) |
Robin Thellend | 912059e | 2014-05-31 18:26:11 -0700 | [diff] [blame^] | 95 | return nil |
Robin Thellend | edca68c | 2014-05-20 11:03:02 -0700 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | // playGame plays an entire game, which really only consists of reading |
| 99 | // commands from the server, and picking a random "move" when asked to. |
| 100 | func (p *Player) playGame(judge string, gameID rps.GameID) (rps.PlayResult, error) { |
| 101 | j, err := rps.BindRockPaperScissors(judge) |
| 102 | if err != nil { |
| 103 | return rps.PlayResult{}, err |
| 104 | } |
| 105 | game, err := j.Play(gameID, veyron2.CallTimeout(10*time.Minute)) |
| 106 | if err != nil { |
| 107 | return rps.PlayResult{}, err |
| 108 | } |
| 109 | for { |
| 110 | in, err := game.Recv() |
| 111 | if err == io.EOF { |
| 112 | vlog.Infof("Game Ended") |
| 113 | break |
| 114 | } |
| 115 | if err != nil { |
| 116 | vlog.Infof("recv error: %v", err) |
| 117 | break |
| 118 | } |
| 119 | if in.PlayerNum > 0 { |
| 120 | vlog.Infof("I'm player %d", in.PlayerNum) |
| 121 | } |
| 122 | if len(in.OpponentName) > 0 { |
| 123 | vlog.Infof("My opponent is %q", in.OpponentName) |
| 124 | } |
| 125 | if len(in.MoveOptions) > 0 { |
| 126 | n := rand.Intn(len(in.MoveOptions)) |
| 127 | vlog.Infof("My turn to play. Picked %q from %v", in.MoveOptions[n], in.MoveOptions) |
| 128 | if err := game.Send(rps.PlayerAction{Move: in.MoveOptions[n]}); err != nil { |
| 129 | return rps.PlayResult{}, err |
| 130 | } |
| 131 | } |
| 132 | if len(in.RoundResult.Moves[0]) > 0 { |
| 133 | vlog.Infof("Player 1 played %q. Player 2 played %q. Winner: %v", |
| 134 | in.RoundResult.Moves[0], in.RoundResult.Moves[1], in.RoundResult.Winner) |
| 135 | } |
| 136 | if len(in.Score.Players) > 0 { |
| 137 | vlog.Infof("Score card: %s", common.FormatScoreCard(in.Score)) |
| 138 | } |
| 139 | } |
| 140 | result, err := game.Finish() |
| 141 | p.gamesPlayed.Add(1) |
| 142 | if err == nil && result.YouWon { |
| 143 | p.gamesWon.Add(1) |
| 144 | } |
| 145 | return result, err |
| 146 | } |