|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- package core
-
- import (
- "errors"
- "sync"
- "sync/atomic"
-
- main "API"
- pb "API/proto"
- thuai6 "API/thuai6"
- )
-
- type Logic struct {
- communication *Communication
- playerType thuai6.PlayerType
- playerID int64
- studentType thuai6.StudentType
- trickerType thuai6.TrickerType
- timer thuai6.IGameTimer
- mtxAI sync.Mutex
- mtxState sync.Mutex
- mtxBuffer sync.Mutex
- cvBuffer *sync.Cond
- cvAI *sync.Cond
- state [2]thuai6.State
- currentState *thuai6.State
- bufferState *thuai6.State
- counterState int32
- counterBuffer int32
- gameState thuai6.GameState
- aiStart bool
- bufferUpdated bool
- aiLoop int32
- freshed int32
- }
-
- func NewLogic(playerType thuai6.PlayerType, id int64, tricker thuai6.TrickerType, student thuai6.StudentType) *Logic {
- logic := &Logic{
- communication: nil,
- playerType: playerType,
- playerID: id,
- studentType: student,
- trickerType: tricker,
- timer: nil,
- mtxAI: sync.Mutex{},
- mtxState: sync.Mutex{},
- mtxBuffer: sync.Mutex{},
- cvBuffer: nil,
- cvAI: nil,
- state: [2]thuai6.State{},
- counterState: 0,
- counterBuffer: 0,
- gameState: thuai6.NullGameState,
- aiStart: false,
- bufferUpdated: true,
- aiLoop: 1,
- freshed: 0,
- }
- logic.currentState = &logic.state[0]
- logic.bufferState = &logic.state[1]
- logic.cvBuffer = sync.NewCond(&logic.mtxBuffer)
- logic.cvAI = sync.NewCond(&logic.mtxAI)
- return logic
- }
-
- func (logic *Logic) GetStudentSelfInfo() *thuai6.Student {
- logic.mtxState.Lock()
- defer logic.mtxState.Unlock()
- return logic.currentState.StudentSelf
- }
-
- func (logic *Logic) GetTrickerSelfInfo() *thuai6.Tricker {
- logic.mtxState.Lock()
- defer logic.mtxState.Unlock()
- return logic.currentState.TrickerSelf
- }
-
- func (logic *Logic) Move(time int64, angle float64) bool {
- return logic.communication.Move(time, angle, logic.playerID)
- }
-
- func (logic *Logic) TryConnection() bool {
- return logic.communication.TryConnection(logic.playerID)
- }
-
- func (logic *Logic) Wait() {
- atomic.StoreInt32(&logic.freshed, 0)
- logic.mtxBuffer.Lock()
- defer logic.mtxBuffer.Unlock()
- for atomic.LoadInt32(&logic.freshed) == 0 {
- logic.cvBuffer.Wait()
- }
- }
-
- func (logic *Logic) Update() {
- if main.Asynchronous == false {
- logic.mtxBuffer.Lock()
- defer logic.mtxBuffer.Unlock()
- for logic.bufferUpdated == false {
- logic.cvBuffer.Wait()
- }
- // Go 的 defer 是函数推出时执行而非 block 退出时执行,故包装一层 func
- func() {
- logic.mtxState.Lock()
- defer logic.mtxState.Unlock()
- var tmpState = logic.currentState
- logic.currentState = logic.bufferState
- logic.bufferState = tmpState
- logic.counterState = logic.counterBuffer
- }()
- logic.bufferUpdated = false
- }
- }
-
- func (logic *Logic) ProcessMessage() <-chan int {
- endChan := make(chan int, 1)
- go func() {
- logic.communication.AddPlayer(logic.playerID, logic.playerType, logic.studentType, logic.trickerType)
- for logic.gameState != thuai6.GameEnd {
- clientMsg := logic.communication.GetMessageToClient()
- logic.gameState = thuai6.GameStateToTHUAI6[clientMsg.GameState]
- switch logic.gameState {
- case thuai6.GameStart:
- playerGUIDs := make([]int64, 0)
- for _, obj := range clientMsg.ObjMessage {
- switch obj.MessageOfObj.(type) {
- case *(pb.MessageOfObj_StudentMessage):
- playerGUIDs = append(playerGUIDs, obj.GetStudentMessage().GetGuid())
- }
- }
- for _, obj := range clientMsg.ObjMessage {
- switch obj.MessageOfObj.(type) {
- case *(pb.MessageOfObj_TrickerMessage):
- playerGUIDs = append(playerGUIDs, obj.GetTrickerMessage().GetGuid())
- }
- }
- logic.currentState.Guids = playerGUIDs
- logic.bufferState.Guids = playerGUIDs
- // TODO: LoadBuffer
- break
- case thuai6.GameEnd:
-
- }
- }
- // TODO: ProcessMessage
- endChan <- 0
- }()
- return endChan
- }
-
- func (logic *Logic) Main(createAI thuai6.CreateAIFunc, ip string, port string) error {
- comm, err := NewCommunication(ip, port)
- if err != nil {
- return err
- }
- logic.communication = comm
-
- if logic.playerType == thuai6.StudentPlayer {
- logic.timer = NewStudentAPI(logic)
- } else if logic.playerType == thuai6.TrickerPlayer {
- logic.timer = NewTrickerAPI(logic)
- } else {
- return errors.New("Invalid player type")
- }
-
- aiThread := func() {
- // Go 的 defer 是函数推出时执行而非 block 退出时执行,故包装一层 func
- func() {
- logic.mtxAI.Lock()
- defer logic.mtxAI.Unlock()
- for logic.aiStart == false {
- logic.cvAI.Wait()
- }
- }()
- ai := createAI(logic.playerID)
-
- for atomic.LoadInt32(&logic.aiLoop) != 0 {
- if main.Asynchronous {
- logic.Wait()
- } else {
- logic.Update()
- }
- logic.timer.StartTimer()
- logic.timer.Play(ai)
- logic.timer.EndTimer()
- }
- }
-
- if logic.TryConnection() == false {
- atomic.StoreInt32(&logic.aiLoop, 0)
- return errors.New("Connection failed.")
- }
-
- aiEnd := make(chan int, 1)
- go func() {
- aiThread()
- aiEnd <- 1
- }()
- <-logic.ProcessMessage()
- <-aiEnd
- return nil
- }
|