5I4UCQOTFNIXNO3IEJBPOHAHI63WOS7ZCOGHWJ47IK6MDJ6CBW6AC CGTXUBZEQ3JIDHM7MY5JDL5LB43L2QECXRS6W3RLTRIVCZTHH4IAC MYLF7NEGFT6YYO6OEK22FLAS6Y2V3YGU4CQIMBE6APOLGLTOFNRQC ZXBDOUETFSXTFY6J5LIMXBCNMDW6NTUTZ7HZZ6ND7BNUKISR74FAC OPI6W7BO4V3R5WGEVN4USOHVPUV5PVWGKYBMCRU4VQOI7F7RCF5QC EZYBNJFUNOS3LIU6ILXN7MFKLVW4SDXW6K5T4YFKFZ2R4UWSFUXAC 4LMTBPV7JT446YP5RLF6HT7246BY75U5V35JTEIK4PT5NEPKNNKAC NDDFOS5624OS3JXFPE46C2VBGU6XYA2XOOP7X5GF26HMDPYLOQXQC NRK37A4NNGLF53STW5RJDHUEP6OKKJORJZL3HYVOKD7OW4QBO5XAC 2KCPYEJPVD4GH2WZIVQY5MY6DSVHGQ2IOZ3V7WQ5Q267B4L6KBUQC M74RMZSTQLQHMG5PGM6DMM7JJFUHHNBS7QPNGJNXCSB4WHQVBTFAC KLQKDNMZA776M73IWLBYAHXLESBVKE44YJS2IAAMYJJLOC3IJMOAC /*Example:public function myAction(){self::setAjaxMode();// Retrieve arguments// Note: these arguments correspond to what has been sent through the javascript "ajaxcall" method$arg1 = self::getArg( "myArgument1", AT_posint, true );$arg2 = self::getArg( "myArgument2", AT_posint, true );// Then, call the appropriate method in your game logic, like "playCard" or "myAction"$this->game->myAction( $arg1, $arg2 );self::ajaxResponse( );
public function solveCase() {self::setAjaxMode();$tile_ids = self::getArg("tile_ids", AT_numberlist, true);$this->game->solveCase(self::numberlistToArray($tile_ids));self::ajaxResponse();
// We start with minigame number 1. There will be 3 minigames in total.self::setGameStateInitialValue( 'minigame', 1 );$this->startNewMinigame(1);
self::setGameStateInitialValue('minigame', 0); // will be increased in st_setupMinigame
function startNewMinigame($n){self::setGameStateValue('minigame', $n);// Get all cards, sort into piles, shuffle piles.$this->cards->moveAllCardsInLocation(null, "offtable");$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('evidence'), 'id'), 'deck');$this->cards->shuffle('deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('crime'), 'id'), 'crime_deck');$this->cards->shuffle('crime_deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('location'), 'id'), 'location_deck');$this->cards->shuffle('location_deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('suspect'), 'id'), 'suspect_deck');$this->cards->shuffle('suspect_deck');// Get all tiles, shuffle them in two decks, associate them with// location slots. Decks are called "cri_tile_d" (crime tile deck) and// "sus_tile_d" (suspect tile deck). VARCHAR(16) ftw!$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_crime'), 'id'), 'cri_tile_d');// $this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_location'), 'id'), 'loc_tile_d'); // the fake one$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_suspect'), 'id'), 'sus_tile_d');$this->cards->shuffle('cri_tile_d');$this->cards->shuffle('sus_tile_d');foreach($this->locations as $loc_id => $loc) {$this->cards->pickCardForLocation('cri_tile_d', 'locslot', $loc['slots']['crime']['id']);// $this->cards->pickCardForLocation('loc_tile_d', 'locslot', $loc['slots']['location']['id']);$this->cards->pickCardForLocation('sus_tile_d', 'locslot', $loc['slots']['suspect']['id']);
// Get the specific location tile (also currently 'offboard') and// put it into its fixed location slot.//// (28 + $loc_id) is the "material id" aka type_arg of the fake// location tile.// var_dump("TILE LOCATIONS");// var_dump($this->cards->getCardsOfType('tile_location', 28 + $loc_id));$temp = $this->cards->getCardsOfType('tile_location', 28 + $loc_id); // required, as array_shift does not want a direct reference$location_tile = array_shift($temp);$this->cards->moveCard($location_tile['id'], 'locslot', $loc['slots']['location']['id']);}// foreach($this->cards->getCardsOfType('tile_location') as $tile_id => $tile) {// }// Main display of evidence cards$this->cards->pickCardsForLocation($this->constants['EVIDENCE_DISPLAY_SIZE'], 'deck', 'evidence_display');// Set up a case for every player and distribute the case cards to their// right neighbor.$players = self::loadPlayersBasicInfos();foreach($players as $player_id => $player) {$this->cards->pickCard('crime_deck', $player_id);$this->cards->pickCard('location_deck', $player_id);$this->cards->pickCard('suspect_deck', $player_id);}// Select a new first player. In minigame 1 it's player_no 1, in// minigame 2 player_no 2 etc.; using module to cover the 'more rounds// than players' case.$next_player_no = ((self::getGameStateValue("minigame") - 1) % count($players)) + 1;$next_player_id = self::getUniqueValueFromDB("SELECT player_id FROM player WHERE player_no = $next_player_no");$this->gamestate->changeActivePlayer($next_player_id);}
/*** Put a new evidence cards on display. Also takes care about reshuffling* the deck if we run out.*/function replenishEvidenceDisplay(){// While auto-reshuffle is still a mystery to me, check here manually.if ($this->cards->countCardInLocation('deck') == 0&& $this->cards->countCardInLocation('discard') > 0) {$this->cards->moveAllCardsInLocation('discard', 'deck');$this->cards->shuffle('deck');}if ($this->cards->countCardInLocation('deck') > 0) {$newCard = $this->cards->pickCardForLocation("deck", "evidence_display");self::notifyAllPlayers('newEvidence', '',array('card_id' => $newCard['id'],'card_type' => $newCard['type_arg'],'discard_is_empty' => $this->cards->countCardInLocation('discard') == 0,));} else {// Rare case, but it could happen. Players are now forced to do// something else. But this is implicit from the UI: no more cards,// no more clicks on them. Solving is always the last ressort.self::notifyAllPlayers('newEvidence',clienttranslate('Evidence cards are exhausted and cannot be played anymore.'),array('deck_is_empty' => $this->cards->countCardInLocation('discard') == 0,'discard_is_empty' => $this->cards->countCardInLocation('discard') == 0,));}}
// Check that this is the player's turn and that it is a "possible action" at this game state (see states.inc.php)self::checkAction( 'playCard' );$player_id = self::getActivePlayerId();// Add your game logic to play a card there...// Notify all players about the card playedself::notifyAllPlayers( "cardPlayed", clienttranslate( '${player_name} plays ${card_name}' ), array('player_id' => $player_id,'player_name' => self::getActivePlayerName(),'card_name' => $card_name,'card_id' => $card_id) );}*/function selectEvidence($card_id) {
function solveCase($tile_ids) {self::checkAction("solveCase");$player_id = self::getActivePlayerId();$case_cards = getPlayerCaseCards($player_id);// Check if player was correctif ($playerCorrect) {// If it was the last player to solve this round, we are done and// can start a new minigame; or even end the game.} else {$this->increasePenalty($player_id);}self::notifyPlayer(self::getActivePlayerId(),'playerTriedToSolve',clienttranslate('You tried to solve'),array());// self::notifyAllPlayers(// 'evidenceSelected',// clienttranslate('${player_name} had no luck following evidence ${card_name}'),// array (// 'i18n' => array ('card_name'),// 'useful' => false,// 'card_id' => $card_id,// 'card_name' => $this->cardBasis[$currentCard['type_arg']]['name'],// 'card_type' => $currentCard['type_arg'],// 'player_id' => $player_id,// 'player_name' => self::getActivePlayerName(),// )// );}
// While auto-reshuffle is still a mystery to me, check here manually.if ($this->cards->countCardInLocation('deck') == 0&& $this->cards->countCardInLocation('discard') > 0) {$this->cards->moveAllCardsInLocation('discard', 'deck');$this->cards->shuffle('deck');
// Get all cards, sort into piles, shuffle piles.$this->cards->moveAllCardsInLocation(null, "offtable");$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('evidence'), 'id'), 'deck');$this->cards->shuffle('deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('crime'), 'id'), 'crime_deck');$this->cards->shuffle('crime_deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('location'), 'id'), 'location_deck');$this->cards->shuffle('location_deck');$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('suspect'), 'id'), 'suspect_deck');$this->cards->shuffle('suspect_deck');// Get all tiles, shuffle them in two decks, associate them with// location slots. Decks are called "cri_tile_d" (crime tile deck) and// "sus_tile_d" (suspect tile deck). VARCHAR(16) ftw!$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_crime'), 'id'), 'cri_tile_d');// $this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_location'), 'id'), 'loc_tile_d'); // the fake one$this->cards->moveCards(array_pluck($this->cards->getCardsOfType('tile_suspect'), 'id'), 'sus_tile_d');$this->cards->shuffle('cri_tile_d');$this->cards->shuffle('sus_tile_d');foreach($this->locations as $loc_id => $loc) {$this->cards->pickCardForLocation('cri_tile_d', 'locslot', $loc['slots']['crime']['id']);// $this->cards->pickCardForLocation('loc_tile_d', 'locslot', $loc['slots']['location']['id']);$this->cards->pickCardForLocation('sus_tile_d', 'locslot', $loc['slots']['suspect']['id']);// Get the specific location tile (also currently 'offboard') and// put it into its fixed location slot.//// (28 + $loc_id) is the "material id" aka type_arg of the fake// location tile.// var_dump("TILE LOCATIONS");// var_dump($this->cards->getCardsOfType('tile_location', 28 + $loc_id));$temp = $this->cards->getCardsOfType('tile_location', 28 + $loc_id); // required, as array_shift does not want a direct reference$location_tile = array_shift($temp);$this->cards->moveCard($location_tile['id'], 'locslot', $loc['slots']['location']['id']);
if ($this->cards->countCardInLocation('deck') > 0) {$newCard = $this->cards->pickCardForLocation("deck", "evidence_display");self::notifyAllPlayers('newEvidence', '',array('card_id' => $newCard['id'],'card_type' => $newCard['type_arg'],'discard_is_empty' => $this->cards->countCardInLocation('discard') == 0,));} else {// Rare case, but it could happen. Players are now forced to do// something else. But this is implicit from the UI: no more cards,// no more clicks on them. Solving is always the last ressort.self::notifyAllPlayers('newEvidence',clienttranslate('Evidence cards are exhausted and cannot be played anymore.'),array('deck_is_empty' => $this->cards->countCardInLocation('discard') == 0,'discard_is_empty' => $this->cards->countCardInLocation('discard') == 0,));
// Main display of evidence cards$this->cards->pickCardsForLocation($this->constants['EVIDENCE_DISPLAY_SIZE'], 'deck', 'evidence_display');// Set up a case for every player and distribute the case cards to their// right neighbor.$players = self::loadPlayersBasicInfos();foreach($players as $player_id => $player) {$this->cards->pickCard('crime_deck', $player_id);$this->cards->pickCard('location_deck', $player_id);$this->cards->pickCard('suspect_deck', $player_id);
// Select a new first player. In minigame 1 it's player_no 1, in// minigame 2 player_no 2 etc.; using module to cover the 'more rounds// than players' case.$next_player_no = ((self::getGameStateValue("minigame") - 1) % count($players)) + 1;$next_player_id = self::getUniqueValueFromDB("SELECT player_id FROM player WHERE player_no = $next_player_no");$this->gamestate->changeActivePlayer($next_player_id);$this->gamestate->nextState(); // always a player turn}function st_gameTurn(){// TODO: First check if the round is over; then we start a new minigame,// or even end the game completely, if we are already in the last// minigame. Round is over once all players solved; or even if a new// round starts and only 1 player remains with an unsolved case.// TODO: Warn the active player when it's their last chance to solve,// i.e. when they are the last one with an unsolved case in the current// minigame.// TODO: only replenish the display if the current minigame keeps going.// Maybe move this code somewhere else?
// Enable tile selection and wire up validation callbackthis.tiles.setSelectionMode(2);dojo.connect(this.tiles, 'onChangeSelection', this, 'validateCaseSelection');// Highlight clickable tiles// TODO: NO CRIME and NO SUSPECT tiles should not be highlighted or selectabledojo.query('.locslot .stockitem').addClass('highlighted');
/*Here, you can defines some utility methods that you can use everywhere in your javascriptscript.*/
validateCaseSelection: function (opts) {var opts = opts || {};var selectedTiles = this.tiles.getSelectedItems() || [];tileinfos = this.gamedatas.tileinfos;// Validationif (opts.strict && selectedTiles.length != 3) {this.showMessage(_("You must select exactly 3 tiles."), "error");return false;} else if (selectedTiles.length > 3) {this.showMessage(_("You must not select more than 3 tiles."), "error");return false;}var hasSelected = {'crime': false, 'suspect': false, 'location': false};selectedTiles.forEach(dojo.hitch(this, function (tile) {var tile_type_arg = parseInt(tile.type, 10);if (hasSelected[tileinfos[tile_type_arg].tiletype]) {this.showMessage(_("You must not select more than one of each type (crime/location/suspect)."), "error");return false;}hasSelected[tileinfos[tile_type_arg].tiletype] = true;// Tiles 1-6 are "NO CRIME/SUSPECT" tiles.if (parseInt(tile_type_arg, 10) <= 6) {this.showMessage(_("You cannot select NO CRIME or NO SUSPECT tiles."), "error");return false;}}));return true;},
// TODO
if (!this.validateCaseSelection({strict: true})) return;// Send the solving request to the servervar action = 'solveCase';if (this.checkAction(action, true)) {this.ajaxcall("/" + this.game_name + "/" + this.game_name + "/" + action + ".html", {tile_ids : this.tiles.getSelectedItems().map(function (tile) { return tile.id }).join(';'),lock : true}, this, function(result) {}, function(is_error) {});} else {}
"transitions" => array("" => STATE_SETUP_MINIGAME)),// Note: ID=2 => your first stateSTATE_SETUP_MINIGAME => array("name" => "setupMinigame","description" => clienttranslate('Setting up the next minigame.'),"type" => "game","action" => "st_setupMinigame","updateGameProgression" => true,