func main() { game := lib2048.NewGame2048() r := game.GetRand() for i := 0; i < 100; i++ { fmt.Println(r.Int() % 4) } fmt.Println(game.String()) for !game.IsGameOver() { var input string fmt.Scanf("%s", &input) var dir lib2048.Direction switch input { case "w": dir = lib2048.Up case "a": dir = lib2048.Left case "s": dir = lib2048.Down case "d": dir = lib2048.Right } game.MakeMove(dir) fmt.Println(game.String()) } }
func CalculateGameState(initial lib2048.Game2048, moves []*lib2048.Move) lib2048.Game2048 { game := lib2048.NewGame2048() game.CloneFrom(initial) for _, m := range moves { game.MakeMove(m.Direction) } return game }
func NewCClient(cservAddr string, gameServHostPort string, interval int) (Cclient, error) { ws, err := doConnect(cservAddr, gameServHostPort) if err != nil { return nil, err } game := lib2048.NewGame2048() cc := &cclient{ ws, game, make([]lib2048.Direction, 0), make(chan int), make(chan int), make(chan int), make(chan int), make(chan util.ClientMove), cservAddr, } // Fire the ticker ticker := time.NewTicker(time.Duration(interval) * time.Millisecond) go cc.tickHandler(ticker) go cc.websocketHandler() return cc, nil }
func (s *Game2048State) String() string { game := lib2048.NewGame2048() game.SetGrid(s.Grid) game.SetScore(s.Score) return fmt.Sprintf("%sWon: %s\nOver: %s\n", game.String(), s.Won, s.Over) }
// NewGameServer creates an instance of a Game Server. It does not return // until it has successfully joined the cluster of game servers and started // its libpaxos service. func NewGameServer(centralServerHostPort, hostname string, port int, pattern string) (GameServer, error) { // RPC Dial to the central server to join the ring c, err := rpc.DialHTTP("tcp", centralServerHostPort) if err != nil { fmt.Println("Could not connect to central server host port via RPC") fmt.Println(err) return nil, err } // Register myself with the central server, obtaining my ID, and a // complete list of all servers in the ring. gshostport := fmt.Sprintf("%s:%d", hostname, port) args := ¢ralrpc.RegisterGameServerArgs{gshostport} var reply centralrpc.RegisterGameServerReply reply.Status = centralrpc.NotReady for reply.Status != centralrpc.OK { err = c.Call("CentralServer.RegisterGameServer", args, &reply) if err != nil { fmt.Println("Could not RPC call method CentralServer.RegisterGameServer") fmt.Println(err) return nil, err } if reply.Status == centralrpc.Full { return nil, errors.New("Could not register with central server, ring FULL") } time.Sleep(REGISTER_RETRY_INTERVAL * time.Millisecond) } // Start the libpaxos service newlibpaxos, err := libpaxos.NewLibpaxos(reply.GameServerID, gshostport, reply.Servers) if err != nil { fmt.Println("Could not start libpaxos") fmt.Println(err) return nil, err } // Websockets client related stuff clients := make(map[int]*client) addCh := make(chan *client) delCh := make(chan *client) doneCh := make(chan bool) errCh := make(chan error) // Debugging setup var vOut, eOut io.Writer if LOG_TO_FILE { now := time.Now().String() var err1, err2 error vOut, err1 = os.Create(fmt.Sprintf("%d_debug_%s.log", reply.GameServerID, now)) eOut, err2 = os.Create(fmt.Sprintf("%d_error_%s.log", reply.GameServerID, now)) if err1 != nil || err2 != nil { panic(err) } } else { vOut = os.Stdout eOut = os.Stderr } LOGV = util.NewLogger(DEBUG_LOG, "DEBUG", vOut) LOGE = util.NewLogger(ERROR_LOG, "ERROR", eOut) gs := &gameServer{ reply.GameServerID, hostname, port, gshostport, newlibpaxos, pattern, sync.Mutex{}, clients, addCh, delCh, doneCh, errCh, 0, make(chan *paxosrpc.ProposalValue, 1000), len(reply.Servers), lib2048.NewGame2048(), make(chan *util.Game2048State, 1000), make(chan *lib2048.Move, 1000), } gs.libpaxos.DecidedHandler(gs.handleDecided) LOGV.Printf("GS node %d loaded libpaxos\n", reply.GameServerID) go gs.ListenForClients() go gs.processMoves() go gs.clientTasker() go gs.clientMasterHandler() return gs, nil }
// Takes a set of moves, finds the majority, manipulates the local game, and // tells the clientTasker to broadcast that state func (gs *gameServer) processMoves() { sizeQueue := make([]int, 0) pendingMoves := make([]lib2048.Move, 0) currentBucketSize := 0 for { select { case proposal := <-gs.newMovesCh: moves := proposal.Moves pendingMoves = append(pendingMoves, moves...) if currentBucketSize == 0 { currentBucketSize = len(moves) } else { sizeQueue = append(sizeQueue, len(moves)) } requiredMoves := currentBucketSize * gs.totalNumGameServers if len(pendingMoves) >= requiredMoves { // Find the majority of the first $requiredMoves moves dirVotes := make(map[lib2048.Direction]int) dirVotes[lib2048.Up] = 0 dirVotes[lib2048.Down] = 0 dirVotes[lib2048.Left] = 0 dirVotes[lib2048.Right] = 0 pendingMovesSubset := pendingMoves[:requiredMoves] pendingMoves = pendingMoves[requiredMoves:] for _, move := range pendingMovesSubset { dirVotes[move.Direction]++ } LOGV.Println("GAME SERVER", gs.id, "currentBucketSize", currentBucketSize) LOGV.Println("GAME SERVER", gs.id, "pendingMovesSubset", util.MovesString(pendingMovesSubset)) var majorityDir lib2048.Direction maxVotes := 0 for dir, votes := range dirVotes { if votes > maxVotes { maxVotes = votes majorityDir = dir } else if votes == maxVotes && dir > majorityDir { majorityDir = dir } } LOGV.Println("GAME SERVER", gs.id, "got majority direction:", majorityDir) // Update the 2048 state gs.game2048.MakeMove(majorityDir) if gs.game2048.IsGameOver() { gs.game2048 = lib2048.NewGame2048() } state := gs.getWrappedState(&majorityDir) gs.stateBroadcastCh <- state // Update the bucket size if len(sizeQueue) > 0 { currentBucketSize = sizeQueue[0] sizeQueue = sizeQueue[1:] } } } } }