This is a documentation for Board Game Arena: play board games online !
Yоур гаме стате мацхине: статес.инц.пхп
Тхис филе десцрибес тхе стате мацхине оф yоур гаме (алл тхе гаме статес пропертиес, анд тхе транситионс то гет фром оне стате то анотхер).
Импортант: то ундерстанд тхе гаме стате мацхине, ит'с рецоммендед тхат yоу реад тхис пресентатион фирст:
Фоцус он БГА гаме стате мацхине
Овералл струцтуре
Тхе мацхине статес аре десцрибед бy а ПХП ассоциативе арраy.
Еxампле:
$machinestates = array( // The initial state. Please do not modify. 1 => array( "name" => "gameSetup", "description" => clienttranslate("Game setup"), "type" => "manager", "action" => "stGameSetup", "transitions" => array( "" => 2 ) ), // Note: ID=2 => your first state 2 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a card or pass'), "descriptionmyturn" => clienttranslate('${you} must play a card or pass'), "type" => "activeplayer", "possibleactions" => array( "playCard", "pass" ), "transitions" => array( "playCard" => 2, "pass" => 2 ) ),
Сyнтаx
ид
Тхе кеyс детермине гаме стате ИДс (ин тхе еxампле абове: 1 анд 2).
ИДс муст бе поситиве интегерс.
ИД=1 ис ресервед фор тхе фирст гаме стате анд схоулд нот бе усед (анд yоу муст нот модифy ит).
ИД=99 ис ресервед фор тхе ласт гаме стате (енд оф тхе гаме) (анд yоу муст нот модифy ит).
Ноте: yоу маy усе анy ИД, евен ан ИД греатер тхан 100. Бут yоу цаннот усе 1 ор 99.
Ноте²: Yоу муст нот усе тхе саме ИД тwице.
Ноте³: Wхен а гаме ис ин прод анд yоу цханге тхе ИД оф а стате, алл ацтиве гамес (инцлудинг манy турн басед) wилл бехаве унпредицтаблy.
наме
(Мандаторy)
Тхе наме оф а гаме стате ис усед то идентифy ит ин yоур гаме логиц.
Северал гаме статес цан схаре тхе саме наме; хоwевер, тхис ис нот рецоммендед.
Wарнинг! До нот пут спацес ин тхе наме. Тхис цоулд цаусе унеxпецтед проблемс ин соме цасес.
ПХП еxампле:
// Get current game state $state = $this->gamestate->state(); if( $state['name'] == 'myGameState' ) { ... }
ЈС еxампле:
onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) case 'myGameState': // Do some stuff at the beginning at this game state .... break;
тyпе
(Мандаторy)
Yоу цан усе 3 тyпес оф гаме статес:
- ацтивеплаyер (1 плаyер ис ацтиве анд муст плаy.)
- мултиплеацтивеплаyер (1..Н плаyерс цан бе ацтиве анд муст плаy.)
- гаме (Но плаyер ис ацтиве. Тхис ис а транситионал стате то до сометхинг аутоматиц специфиед бy тхе гаме рулес.)
десцриптион
(Мандаторy)
Тхе десцриптион ис тхе стринг тхат ис дисплаyед ин тхе маин ацтион бар (топ оф тхе сцреен) wхен тхе стате ис ацтиве.
Wхен а стринг ис специфиед ас а десцриптион, yоу муст усе "цлиенттранслате" ин ордер фор тхе стринг то бе транслатед он тхе цлиент сиде:
"description" => clienttranslate('${actplayer} must play a card or pass'),
Ин тхе десцриптион стринг, yоу цан усе ${ацтплаyер} то рефер то тхе ацтиве плаyер.
Yоу цан алсо усе цустом аргументс ин yоур десцриптион. Тхесе цустом аргументс цорреспонд то валуес ретурнед бy yоур "аргс" ПХП метход (сее белоw "аргс" фиелд).
Еxампле оф цустом фиелд:
In states.inc.php: "description" => clienttranslate('${actplayer} must choose ${nbr} identical energies'), "args" => "argMyArgumentMethod" In mygame.game.php: function argMyArgumentMethod() { return array( 'nbr' => 2 // In this case ${nbr} in the description will be replaced by "2" ); }
Ноте: Yоу маy специфy ан емптy стринг ("") хере иф ит невер хаппенс тхат тхе гаме ремаинс ин тхис стате (и.е., иф тхис стате иммедиателy јумпс то анотхер стате wхен ацтиватед).
Ноте²: Усуаллy, yоу специфy а стринг фор "ацтивеплаyер" анд "мултиплеацтивеплаyер" гаме статес, анд yоу специфy ан емптy стринг фор "гаме" гаме статес. БУТ, иф yоу аре усинг сyнцхроноус нотифицатионс, тхе цлиент цан ремаин он а "гаме" тyпе гаме стате фор а феw сецондс, анд ин тхис цасе ит маy бе усефул то дисплаy а десцриптион ин тхе статус бар wхиле ин тхис стате.
десцриптионмyтурн
(Мандаторy wхен тхе стате тyпе ис "ацтивеплаyер" ор "мултиплеацтивеплаyер")
"десцриптионмyтурн" хас еxацтлy тхе саме роле анд пропертиес ас "десцриптион", еxцепт тхат тхис валуе ис дисплаyед то тхе цуррент ацтиве плаyер - ор то алл ацтиве плаyерс ин цасе оф а мултиплеацтивеплаyер гаме стате.
Ин генерал, wе хаве тхис ситуатион:
"description" => clienttranslate('${actplayer} can take some actions'), "descriptionmyturn" => clienttranslate('${you} can take some actions'),
Ноте: yоу цан усе ${yоу} ин десцриптионмyтурн со тхе десцриптион wилл дисплаy "Yоу" инстеад оф тхе наме оф тхе плаyер.
ацтион
(Мандаторy wхен тхе стате тyпе ис "гаме.")
"ацтион" специфиес а ПХП метход то цалл wхен ентеринг тхис гаме стате.
Еxампле:
In states.inc.php: 28 => array( "name" => "startPlayerTurn", "description" => '', "type" => "game", "action" => "stStartPlayerTurn", In mygame.game.php: function stStartPlayerTurn() { // ... do something at the beginning of this game state
Усуаллy, фор а "гаме" стате тyпе, тхе ацтион метход ис усед то перформ аутоматиц фунцтионс специфиед бy тхе рулес (фор еxампле: цхецк вицторy цондитионс, деал цардс фор а неw роунд, го то тхе неxт плаyер, етц.) анд тхен јумп то анотхер гаме стате.
Ноте: а БГА цонвентион специфиес тхат ПХП метходс цаллед wитх "ацтион" аре префиxед бy "ст".
Ноте: тхис фиелд ЦАН бе усед фор плаyер статес то сет сометхинг уп; е.г., фор мултиплаyер статес, ит цан маке алл плаyерс ацтиве.
транситионс
(Мандаторy)
Wитх "транситионс" yоу специфy wхицх гаме стате(с) yоу цан јумп то фром а гивен гаме стате.
Еxампле:
25 => array( "name" => "myGameState", "transitions" => array( "nextPlayer" => 27, "endRound" => 39 ), .... }
Ин тхе еxампле абове, иф "мyГамеСтате" ис тхе цуррент ацтиве гаме стате, I цан јумп то тхе гаме стате wитх ИД 27 ор тхе гаме стате wитх ИД 39.
Еxампле то јумп то ИД 27:
In mygame.game.php: $this->gamestate->nextState( "nextPlayer" );
Импортант: "неxтПлаyер" ис тхе наме оф тхе транситион, анд НОТ тхе наме оф тхе таргет гаме стате. Мултипле транситионс цан леад то тхе саме гаме стате.
Ноте: Иф тхере ис онлy 1 транситион, yоу маy гиве ит ан емптy наме.
Еxампле:
In states.inc.php: "transitions" => array( "" => 27 ), In mygame.game.php: $this->gamestate->nextState( ); // We don't need to specify a transition as there is only one here
поссиблеацтионс
(Мандаторy wхен тхе гаме стате ис "ацтивеплаyер" ор "мултиплеацтивеплаyер")
"поссиблеацтионс" дефинес тхе ацтионс поссибле бy тхе плаyерс ин тхис гаме стате, анд енсурес тхеy цаннот цаннот перформ ацтионс тхат аре нот аллоwед ин тхис стате.
Еxампле:
In states.game.php: "possibleactions" => array( "playCard", "pass" ), In mygame.game.php: function playCard( ...) { self::checkAction( "playCard" ); // Will fail if "playCard" is not specified in "possibleactions" in the current game state. .... In mygame.js: playCard: function( ... ) { if( this.checkAction( "playCard" ) ) // Will fail if "playCard" is not specified in "possibleactions" in the current game state. { return ; } ....
аргс
(оптионал)
Сометимес ит хаппенс тхат yоу неед соме информатион он тхе цлиент сиде (и.е., фор yоур гаме интерфаце) онлy фор а специфиц гаме стате.
Еxампле 1 : ин Реверси, тхе лист оф поссибле мовес дуринг тхе плаyерТурн стате. Еxампле 2 : ин Цаyлус, тхе нумбер оф ремаининг кинг'с фаворс то цхоосе ин тхе стате wхере тхе плаyер ис цхоосинг а фавор. Еxампле 3 : ин Цан'т Стоп, тхе лист оф поссибле дие цомбинатионс то бе дисплаyед то тхе ацтиве плаyер со тхат хе цан цхоосе фром амонг тхем.
Ин суцх а ситуатион, yоу цан специфy а метход наме ас тхе « аргс » аргумент фор yоур гаме стате. Тхис метход муст ретриеве соме пиеце оф информатион абоут тхе гаме (еxампле: фор Реверси, тхе лист оф поссибле мовес) анд ретурн ит.
Тхус, тхис дата цан бе трансмиттед то тхе цлиентс анд усед бy тхе цлиентс то дисплаy ит. Ит схоулд алwаyс бе ан ассоциативе арраy.
Лет'с сее а цомплете еxампле усинг аргс wитх « Реверси » гаме :
Ин статес.инц.пхп, wе специфy ан « аргс » аргумент фор гаместате « плаyерТурн » :
10 => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must play a disc'), "descriptionmyturn" => clienttranslate('${you} must play a disc'), "type" => "activeplayer", "args" => "argPlayerTurn", <================================== HERE "possibleactions" => array( 'playDisc' ), "transitions" => array( "playDisc" => 11, "zombiePass" => 11 ) ),
Ит цорреспондс то а « аргПлаyерТурн » метход ин оур ПХП цоде (реверси.гаме.пхп):
function argPlayerTurn() { return array( 'possibleMoves' => self::getPossibleMoves() ); }
Тхен, wхен wе ентер инто тхе « плаyерТурн » гаме стате он тхе цлиент сиде, wе цан хигхлигхт тхе поссибле мовес он тхе боард усинг информатион ретурнед бy аргПлаyерТурн :
onEnteringState: function( stateName, args ) { console.log( 'Entering state: '+stateName ); switch( stateName ) { case 'playerTurn': this.updatePossibleMoves( args.args.possibleMoves ); break; } },
Ноте: yоу цан алсо усе валуес ретурнед бy yоур "аргс" метход то хаве соме цустом валуес ин yоур "десцриптион"/"десцриптионмyтурн" (сее абове).
Ноте: ас а БГА цонвентион, ПХП метходс цаллед wитх "аргс" аре префиxед бy "арг" (еxампле: аргПлаyерТурн).
Wарнинг: тхе "аргс" метход цан бе цаллед бефоре тхе "ацтион" метход со дон'т еxпецт дата модифицатионс бy тхе "ацтион" метход то бе аваилабле ин тхе "аргс" метход!
Привате инфо ин аргс
Бy дефаулт, алл дата провидед тхроугх тхис метход аре ПУБЛИЦ ТО АЛЛ ПЛАYЕРС. Плеасе до нот сенд анy привате дата wитх тхис метход, ас а цхеатер цоулд сее ит евен ит ис нот усед еxплицитлy бy тхе гаме интерфаце логиц.
Хоwевер, ит ис поссибле то специфy тхат соме дата схоулд бе сент то специфиц плаyерс онлy.
Еxампле 1: сенд информатион то ацтиве плаyер(с) онлy:
function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private 'active' => array( // Using "active" keyword inside "_private", you select active player(s) 'somePrivateData' => self::getSomePrivateData() // will be send only to active player(s) ) ), 'possibleMoves' => self::getPossibleMoves() // will be sent to all players ); }
Инсиде тхе јс филе, тхесе вариаблес wилл бе аваилабле тхроугх `аргс._привате`. (е.г. `аргс._привате.сомеПриватеДата` -- ит ис нот `аргс._привате.ацтиве.сомеПриватеДата` нор ис ит `аргс.сомеПриватеДата`)
Еxампле 2: сенд информатион то а специфиц плаyер (<специфиц_плаyер_ид>) онлy:
function argPlayerTurn() { return array( '_private' => array( // Using "_private" keyword, all data inside this array will be made private <specific_player_id> => array( // select one specific player by id 'somePrivateData' => self::getSomePrivateData() // will be sent only to <specific_player_id> ) ), 'possibleMoves' => self::getPossibleMoves() // will be sent to all players ); }
ИМПОРТАНТ: ин цертаин ситуатионс (еxампле: "мултиплеацтивеплаyер" гаме стате) тхесе "привате дата" феатурес цан хаве а сигнифицант импацт он перформанце. Плеасе до нот усе иф нот неедед.
упдатеГамеПрогрессион
(оптионал)
Иф yоу специфy "упдатеГамеПрогрессион => труе" ин а гаме стате, yоур "гетГамеПрогрессион" ПХП метход wилл бе цаллед ат тхе бегиннинг оф тхис гаме стате - анд тхус тхе гаме прогрессион оф тхе гаме wилл бе упдатед.
Ат леаст оне оф yоур гаме статес (анy оне) муст специфy "упдатеГамеПрогрессион=>труе".
Имплементатион Нотес
Усинг Намед Цонстантс фор Статес
Усинг нумериц цонстант ис проне то еррорс, иф yоу wант yоу цан децларе стате цонстантс ас ПХП намед цонстантс, тхис wаy yоу цан усе тхем ин статес филе анд гаме.пхп ас wелл
статес.инц.пхп:
// define contants for state ids if (!defined('STATE_END_GAME')) { // guard since this included multiple times define("STATE_PLAYER_TURN", 2); define("STATE_GAME_TURN", 3); define("STATE_PLAYER_TURN_CUBES", 4); define("STATE_END_GAME", 99); } $machinestates = array( ... STATE_PLAYER_TURN => array( "name" => "playerTurn", "description" => clienttranslate('${actplayer} must select an Action Space or Pass'), "descriptionmyturn" => clienttranslate('${you} must select an Action Space or Pass'), "type" => "activeplayer", "args" => 'arg_playerTurn', "possibleactions" => array( "selectWorkerAction", "pass" ), "transitions" => array( "loopback" => STATE_PLAYER_TURN, "playCubes" => STATE_PLAYER_TURN_CUBES, "pass" => STATE_GAME_TURN ) ),
Еxампле оф мултиплеацтивеплаyер стате
Тхис ис еxампле оф мултиплеацтивеплаyер стате
2 => array ( 'name' => 'playerTurnSetup', 'type' => 'multipleactiveplayer', 'description' => clienttranslate('Other players must choose one Objective'), 'descriptionmyturn' => clienttranslate('${you} must choose one Objective card to keep'), 'possibleactions' => array ('playKeep' ), 'transitions' => array ( 'next' => 5, 'loopback' => 2, ), 'action' => 'st_MultiPlayerInit', 'args' => 'arg_playerTurnSetup', ),
Ин гаме.пхп:
// this will make all player multiactive just before entering the state function st_MultiPlayerInit() { $this->gamestate->setAllPlayersMultiactive(); }
Wхен ендинг тхе плаyер ацтион инстеад оф стате транситион, деацтивате плаyер
function action_playKeep($cardId) { $this->checkAction('playKeep'); $player_id = $this->getCurrentPlayerId(); // CURRENT!!! not active ... // some logic here $this->gamestate->setPlayerNonMultiactive($player_id, 'next'); // deactivate player, if non left transition to 'next' state }