Пример #1
0
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())
	}
}
Пример #2
0
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
}
Пример #4
0
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)
}
Пример #5
0
// 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 := &centralrpc.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
}
Пример #6
0
// 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:]
				}
			}

		}
	}
}