@@ -41,6 +41,24 @@ export function LocalMaster(game) {
4141 return master ;
4242}
4343
44+ /**
45+ * Returns null if it is not a bot's turn.
46+ * Otherwise, returns a playerID of a bot that may play now.
47+ */
48+ export function GetBotPlayer ( state , bots ) {
49+ if ( state . ctx . stage ) {
50+ for ( const key of Object . keys ( bots ) ) {
51+ if ( key in state . ctx . stage ) {
52+ return key ;
53+ }
54+ }
55+ } else if ( state . ctx . currentPlayer in bots ) {
56+ return state . ctx . currentPlayer ;
57+ }
58+
59+ return null ;
60+ }
61+
4462/**
4563 * Local
4664 *
@@ -58,27 +76,70 @@ export class LocalTransport extends Transport {
5876 * @param {string } numPlayers - The number of players.
5977 * @param {string } server - The game server in the form of 'hostname:port'. Defaults to the server serving the client if not provided.
6078 */
61- constructor ( { master, store, gameID, playerID, gameName, numPlayers } ) {
79+ constructor ( {
80+ master,
81+ bots,
82+ game,
83+ store,
84+ gameID,
85+ playerID,
86+ gameName,
87+ numPlayers,
88+ } ) {
6289 super ( { store, gameName, playerID, gameID, numPlayers } ) ;
6390
6491 this . master = master ;
92+ this . game = game ;
6593 this . isConnected = true ;
94+
95+ if ( game && game . ai && bots ) {
96+ this . bots = { } ;
97+
98+ for ( const playerID in bots ) {
99+ const bot = bots [ playerID ] ;
100+ this . bots [ playerID ] = new bot ( {
101+ game,
102+ enumerate : game . ai . enumerate ,
103+ seed : game . seed ,
104+ } ) ;
105+ }
106+ }
66107 }
67108
68109 /**
69110 * Called when another player makes a move and the
70111 * master broadcasts the update to other clients (including
71112 * this one).
72113 */
73- onUpdate ( gameID , state , deltalog ) {
114+ async onUpdate ( gameID , state , deltalog ) {
74115 const currentState = this . store . getState ( ) ;
75116
76117 if ( gameID == this . gameID && state . _stateID >= currentState . _stateID ) {
77118 const action = ActionCreators . update ( state , deltalog ) ;
78119 this . store . dispatch ( action ) ;
120+
121+ if ( this . bots ) {
122+ const newState = this . store . getState ( ) ;
123+ const botPlayer = GetBotPlayer ( newState , this . bots ) ;
124+ if ( botPlayer !== null ) {
125+ setTimeout ( async ( ) => {
126+ await this . makeBotMove ( newState , botPlayer ) ;
127+ } , 100 ) ;
128+ }
129+ }
79130 }
80131 }
81132
133+ async makeBotMove ( state , playerID ) {
134+ const botAction = await this . bots [ playerID ] . play ( state , playerID ) ;
135+ await this . master . onUpdate (
136+ botAction . action ,
137+ state . _stateID ,
138+ this . gameID ,
139+ botAction . action . payload . playerID
140+ ) ;
141+ }
142+
82143 /**
83144 * Called when the client first connects to the master
84145 * and requests the current game state.
@@ -149,7 +210,7 @@ export class LocalTransport extends Transport {
149210}
150211
151212const localMasters = new Map ( ) ;
152- export function Local ( ) {
213+ export function Local ( opts ) {
153214 return transportOpts => {
154215 let master ;
155216
@@ -160,6 +221,10 @@ export function Local() {
160221 localMasters . set ( transportOpts . gameKey , master ) ;
161222 }
162223
163- return new LocalTransport ( { master, ...transportOpts } ) ;
224+ return new LocalTransport ( {
225+ master,
226+ bots : opts && opts . bots ,
227+ ...transportOpts ,
228+ } ) ;
164229 } ;
165230}
0 commit comments