Skip to content

Latest commit

 

History

History
623 lines (494 loc) · 24.8 KB

07.md

File metadata and controls

623 lines (494 loc) · 24.8 KB
title actions requireLogin material
금지된 카드 적용하기
checkAnswer
hints
false
editor
language startingCode answer
solidity
examplegame.sol ZBGameMode.sol ZBSerializer.sol
pragma solidity 0.4.25; import "./ZB/ZBGameMode.sol"; contract ExampleGame is ZBGameMode { mapping (string => bool) internal bannedCards; constructor() public { // Set rules for which cards are banned from play bannedCards["Leash"] = true; bannedCards["Bulldozer"] = true; bannedCards["Lawnmower"] = true; bannedCards["Shopping Cart"] = true; bannedCards["Stapler"] = true; bannedCards["Nail Bomb"] = true; bannedCards["Goo Bottles"] = true; bannedCards["Molotov"] = true; bannedCards["Super Goo Serum"] = true; bannedCards["Junk Spear"] = true; bannedCards["Fire Extinguisher"] = true; bannedCards["Fresh Meat"] = true; bannedCards["Chainsaw"] = true; bannedCards["Bat"] = true; bannedCards["Whistle"] = true; bannedCards["Supply Drop"] = true; bannedCards["Goo Beaker"] = true; bannedCards["Zed Kit"] = true; bannedCards["Torch"] = true; bannedCards["Shovel"] = true; bannedCards["Boomstick"] = true; bannedCards["Tainted Goo"] = true; bannedCards["Corrupted Goo"] = true; } function beforeMatchStart(bytes serializedGameState) external { GameState memory gameState; gameState.init(serializedGameState); ZBSerializer.SerializedGameStateChanges memory changes; changes.init(); // Changes to base game stats changes.changePlayerDefense(Player.Player1, 15); changes.changePlayerDefense(Player.Player2, 15); changes.changePlayerCurrentGooVials(Player.Player1, 3); changes.changePlayerCurrentGooVials(Player.Player2, 3); changes.changePlayerCurrentGoo(Player.Player1, 3); changes.changePlayerCurrentGoo(Player.Player2, 3); changes.changePlayerMaxGooVials(Player.Player1, 8); changes.changePlayerMaxGooVials(Player.Player2, 8); // 여기서 시작하게 } }
// This file is here for your reference, but doesn't contain all the imports necessary // to compile. You can find a repo with all the final files at: // https://github.com/loomnetwork/zb_game_mode pragma solidity ^0.4.25; import "./ZBEnum.sol"; import "./ZBSerializer.sol"; contract ZBGameMode { using ZBSerializer for ZBSerializer.SerializedGameStateChanges; using ZBSerializer for GameState; enum Player { Player1, Player2 } struct PlayerState { string id; //PlayerActionType currentAction = 2; //OverlordInstance overlordInstance = 3; CardInstance[] cardsInHand; //CardInstance[] CardsInPlay; CardInstance[] cardsInDeck; Deck deck; uint8 defense; uint8 currentGoo; uint8 gooVials; uint32 turnTime; //bool hasDrawnCard = 11; //repeated CardInstance cardsInGraveyard = 12; uint8 initialCardsInHandCount; uint8 maxCardsInPlay; uint8 maxCardsInHand; uint8 maxGooVials; } struct Deck { int64 id; string name; int64 heroId; } struct CardInstance { int32 instanceId; string mouldName; int32 defense; bool defenseInherited; int32 attack; bool attackInherited; int32 gooCost; bool gooCostInherited; } struct GameState { int64 id; uint8 currentPlayerIndex; PlayerState[] playerStates; } struct Vector2Int { int32 x; int32 y; } struct Rect { Vector2Int position; Vector2Int size; } struct CustomUiLabel { Rect rect; string text; } struct CustomUiButton { Rect rect; string title; bytes onClickCallData; } event GameStateChanges ( bytes serializedChanges ); function getInterfaceVersion() external pure returns (int) { return 1; } function getDataStructureVersion() external pure returns (int) { return 1; } function beforeMatchStart(bytes) external { } function afterInitialDraw(bytes) external { } function getCustomUi() external view returns (bytes) { return new bytes(0); } }
// This file is here for your reference, but doesn't contain all the imports necessary // to compile. You can find a repo with all the final files at: // https://github.com/loomnetwork/zb_game_mode pragma solidity ^0.4.25; import "./ZBEnum.sol"; import "./ZBGameMode.sol"; import "./SerialityBinaryStream.sol"; library ZBSerializer { using SerialityBinaryStream for SerialityBinaryStream.BinaryStream; uint constant defaultSerializedGameStateChangesBufferSize = 512; uint constant defaultSerializedCustomUiBufferSize = 512; event GameStateChanges ( bytes serializedChanges ); struct SerializedGameStateChanges { SerialityBinaryStream.BinaryStream stream; } struct SerializedCustomUi { SerialityBinaryStream.BinaryStream stream; } // GameState deserialization function init(ZBGameMode.GameState memory self, bytes serializedGameState) internal pure { SerialityBinaryStream.BinaryStream memory stream = SerialityBinaryStream.BinaryStream(serializedGameState, serializedGameState.length); self.id = stream.readInt64(); self.currentPlayerIndex = stream.readUint8(); self.playerStates = new ZBGameMode.PlayerState[](2); for (uint i = 0; i < self.playerStates.length; i++) { self.playerStates[i] = deserializePlayerState(stream); } } function deserializePlayerState(SerialityBinaryStream.BinaryStream memory stream) private pure returns (ZBGameMode.PlayerState) { ZBGameMode.PlayerState memory player; player.id = stream.readString(); player.deck = deserializeDeck(stream); player.cardsInHand = deserializeCardInstanceArray(stream); player.cardsInDeck = deserializeCardInstanceArray(stream); player.defense = stream.readUint8(); player.currentGoo = stream.readUint8(); player.gooVials = stream.readUint8(); player.turnTime = stream.readUint32(); player.initialCardsInHandCount = stream.readUint8(); player.maxCardsInPlay = stream.readUint8(); player.maxCardsInHand = stream.readUint8(); player.maxGooVials = stream.readUint8(); return player; } function serializeCardInstance(SerialityBinaryStream.BinaryStream memory stream, ZBGameMode.CardInstance card) private pure { stream.writeInt32(card.instanceId); stream.writeString(card.mouldName); stream.writeInt32(card.defense); stream.writeBool(card.attackInherited); stream.writeInt32(card.attack); stream.writeBool(card.defenseInherited); stream.writeInt32(card.gooCost); stream.writeBool(card.gooCostInherited); } function deserializeCardInstance(SerialityBinaryStream.BinaryStream memory stream) private pure returns (ZBGameMode.CardInstance) { ZBGameMode.CardInstance memory card; card.instanceId = stream.readInt32(); card.mouldName = stream.readString(); card.defense = stream.readInt32(); card.defenseInherited = stream.readBool(); card.attack = stream.readInt32(); card.attackInherited = stream.readBool(); card.gooCost = stream.readInt32(); card.gooCostInherited = stream.readBool(); return card; } function serializeCardInstanceArray(SerialityBinaryStream.BinaryStream memory stream, ZBGameMode.CardInstance[] cards) internal pure { stream.writeUint32(uint32(cards.length)); for (uint i = 0; i < cards.length; i++) { serializeCardInstance(stream, cards[i]); } } function deserializeCardInstanceArray(SerialityBinaryStream.BinaryStream memory stream) private pure returns (ZBGameMode.CardInstance[]) { uint count = stream.readUint32(); ZBGameMode.CardInstance[] memory cards = new ZBGameMode.CardInstance[](count); for (uint i = 0; i < count; i++) { cards[i] = deserializeCardInstance(stream); } return cards; } function deserializeDeck(SerialityBinaryStream.BinaryStream memory stream) private pure returns (ZBGameMode.Deck) { ZBGameMode.Deck memory deck; deck.id = stream.readInt64(); deck.name = stream.readString(); deck.heroId = stream.readInt64(); return deck; } function serializeStartGameStateChangeAction( SerialityBinaryStream.BinaryStream memory stream, ZBEnum.GameStateChangeAction action ) private pure { stream.writeUint32(uint32(action)); } function serializeStartGameStateChangeAction( SerialityBinaryStream.BinaryStream memory stream, ZBEnum.GameStateChangeAction action, ZBGameMode.Player player ) private pure { stream.writeUint32(uint32(action)); stream.writeUint8(uint8(player)); } // CardInstance function changeMouldName(ZBGameMode.CardInstance memory self, string mouldName) internal pure { self.mouldName = mouldName; } function changeDefense(ZBGameMode.CardInstance memory self, uint8 defense) internal pure { self.defense = defense; self.defenseInherited = false; } function changeAttack(ZBGameMode.CardInstance memory self, uint8 attack) internal pure { self.attack = attack; self.attackInherited = false; } function changeGooCost(ZBGameMode.CardInstance memory self, uint8 gooCost) internal pure { self.gooCost = gooCost; self.gooCostInherited = false; } // SerializedGameStateChanges function init(SerializedGameStateChanges memory self) internal pure { init(self, defaultSerializedGameStateChangesBufferSize); } function init(SerializedGameStateChanges memory self, uint bufferSize) internal pure { self.stream = SerialityBinaryStream.BinaryStream(new bytes(bufferSize), bufferSize); } function getBytes(SerializedGameStateChanges memory self) internal pure returns (bytes) { return self.stream.buffer; } function emit(SerializedGameStateChanges memory self) internal { emit GameStateChanges(getBytes(self)); } function changePlayerDefense(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 defense) internal pure returns (uint) { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerDefense, player); stream.writeUint8(uint8(defense)); } function changePlayerCurrentGoo(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 currentGoo) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerCurrentGoo, player); stream.writeUint8(uint8(currentGoo)); } function changePlayerCurrentGooVials(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 gooVials) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerGooVials, player); stream.writeUint8(uint8(gooVials)); } function changePlayerCardsInDeck( SerializedGameStateChanges memory self, ZBGameMode.Player player, ZBGameMode.CardInstance[] cards, uint cardCount ) internal pure { require( cardCount <= cards.length, "cardCount > cards.length" ); SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerCardsInDeck, player); stream.writeUint32(uint32(cardCount)); for (uint i = 0; i < cardCount; i++) { serializeCardInstance(stream, cards[i]); } } function changePlayerCardsInDeck( SerializedGameStateChanges memory self, ZBGameMode.Player player, ZBGameMode.CardInstance[] cards ) internal pure { changePlayerCardsInDeck(self, player, cards, cards.length); } function changePlayerCardsInHand( SerializedGameStateChanges memory self, ZBGameMode.Player player, ZBGameMode.CardInstance[] cards, uint cardCount ) internal pure { require( cardCount <= cards.length, "cardCount > cards.length" ); SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerCardsInHand, player); stream.writeUint32(uint32(cardCount)); for (uint i = 0; i < cardCount; i++) { serializeCardInstance(stream, cards[i]); } } function changePlayerCardsInHand( SerializedGameStateChanges memory self, ZBGameMode.Player player, ZBGameMode.CardInstance[] cards ) internal pure { changePlayerCardsInHand(self, player, cards, cards.length); } function changePlayerInitialCardsInHandCount(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 count) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerInitialCardsInHandCount, player); stream.writeUint8(count); } function changePlayerMaxCardsInPlay(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 count) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerMaxCardsInPlay, player); stream.writeUint8(count); } function changePlayerMaxCardsInHand(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 count) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerMaxCardsInHand, player); stream.writeUint8(count); } function changePlayerMaxGooVials(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint8 count) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerMaxGooVials, player); stream.writeUint8(count); } function changePlayerTurnTime(SerializedGameStateChanges memory self, ZBGameMode.Player player, uint32 turnTime) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartGameStateChangeAction(stream, ZBEnum.GameStateChangeAction.SetPlayerTurnTime, player); stream.writeUint32(turnTime); } // SerializedCustomUi function init(SerializedCustomUi memory self) internal pure { init(self, defaultSerializedCustomUiBufferSize); } function init(SerializedCustomUi memory self, uint bufferSize) internal pure { self.stream = SerialityBinaryStream.BinaryStream(new bytes(bufferSize), bufferSize); } function getBytes(SerializedCustomUi memory self) internal pure returns (bytes) { return self.stream.buffer; } function add(SerializedCustomUi memory self, ZBGameMode.CustomUiLabel label) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartCustomUiElement(stream, ZBEnum.CustomUiElement.Label, label.rect); stream.writeString(label.text); } function add(SerializedCustomUi memory self, ZBGameMode.CustomUiButton button) internal pure { SerialityBinaryStream.BinaryStream memory stream = self.stream; serializeStartCustomUiElement(stream, ZBEnum.CustomUiElement.Button, button.rect); stream.writeString(button.title); stream.writeBytes(button.onClickCallData); } function serializeStartCustomUiElement(SerialityBinaryStream.BinaryStream memory stream, ZBEnum.CustomUiElement element) private pure { stream.writeInt32(int32(element)); } function serializeStartCustomUiElement( SerialityBinaryStream.BinaryStream memory stream, ZBEnum.CustomUiElement element, ZBGameMode.Rect rect ) private pure { serializeStartCustomUiElement(stream, element); serializeRect(stream, rect); } function serializeRect(SerialityBinaryStream.BinaryStream memory stream, ZBGameMode.Rect rect) private pure { serializeVector2Int(stream, rect.position); serializeVector2Int(stream, rect.size); } function serializeVector2Int(SerialityBinaryStream.BinaryStream memory stream, ZBGameMode.Vector2Int v) private pure { stream.writeInt32(v.x); stream.writeInt32(v.y); } }
pragma solidity 0.4.25; import "./ZB/ZBGameMode.sol"; contract ExampleGame is ZBGameMode { mapping (string => bool) internal bannedCards; constructor() public { // Set rules for which cards are banned from play bannedCards["Leash"] = true; bannedCards["Bulldozer"] = true; bannedCards["Lawnmower"] = true; bannedCards["Shopping Cart"] = true; bannedCards["Stapler"] = true; bannedCards["Nail Bomb"] = true; bannedCards["Goo Bottles"] = true; bannedCards["Molotov"] = true; bannedCards["Super Goo Serum"] = true; bannedCards["Junk Spear"] = true; bannedCards["Fire Extinguisher"] = true; bannedCards["Fresh Meat"] = true; bannedCards["Chainsaw"] = true; bannedCards["Bat"] = true; bannedCards["Whistle"] = true; bannedCards["Supply Drop"] = true; bannedCards["Goo Beaker"] = true; bannedCards["Zed Kit"] = true; bannedCards["Torch"] = true; bannedCards["Shovel"] = true; bannedCards["Boomstick"] = true; bannedCards["Tainted Goo"] = true; bannedCards["Corrupted Goo"] = true; } function beforeMatchStart(bytes serializedGameState) external { GameState memory gameState; gameState.init(serializedGameState); ZBSerializer.SerializedGameStateChanges memory changes; changes.init(); // Changes to base game stats changes.changePlayerDefense(Player.Player1, 15); changes.changePlayerDefense(Player.Player2, 15); changes.changePlayerCurrentGooVials(Player.Player1, 3); changes.changePlayerCurrentGooVials(Player.Player2, 3); changes.changePlayerCurrentGoo(Player.Player1, 3); changes.changePlayerCurrentGoo(Player.Player2, 3); changes.changePlayerMaxGooVials(Player.Player1, 8); changes.changePlayerMaxGooVials(Player.Player2, 8); // Go through each player's deck and modify it to remove banned cards for (uint i = 0; i < gameState.playerStates.length; i++) { CardInstance[] memory newCards = new CardInstance[](gameState.playerStates[i].cardsInDeck.length); uint cardCount = 0; } } }

이제 우리의 게임 모드에서 금지되는 카드들의 목록을 정의했으니, 각 플레이어의 덱에 있는 카드를 검사하고 허용되지 않는 카드를 제거하는 로직을 만들어야 하네.

솔리디티에서 배열의 한 요소를 지우는 것이 간단하지 않기 때문에, 메모리에 새 배열을 만들고 "허용되는" 카드들을 모두 복사해 넣는 것이 더 쉬울 것이네.

이를 위해 우리가 해야 할 것들을 알아보도록 하지.

플레이어 리스트와 상호작용하기

우리의 gameState가 지금 현재 게임 상태의 모든 정보들을 가지고 있다는 것을 상기해보게. 두 플레이어와 그 카드들까지 포함하고 있지.

두 플레이어의 정보들은 gameState.playerStates에 저장되어 있네.

각 플레이어의 정보를 하나하나 확인하기 위해 우리는 다음의 for 반복문을 사용할 수 있지:

for (uint i = 0; i < gameState.playerStates.length; i++) {
    // 각 플레이어(gameState.playerStates[i])에 대한 어떤 행동 처리
}

새로운 카드 배열 선언하기

CardInstance는 카드들의 데이터를 저장하는, ZBGameMode에서 불러온 구조체이네:

struct CardInstance {
    int32 instanceId;
    string mouldName;
    int32 defense;
    bool defenseInherited;
    int32 attack;
    bool attackInherited;
    int32 gooCost;
    bool gooCostInherited;
}

허용되는 카드들을 하나하나 복사해 넣을 수 있도록 각 플레이어의 새로운 카드 배열을 만들기 위해, 우리는 다음과 같이 할 수 있네:

// 길이 30짜리 CardInstances 배열 만들기(카드 30개짜리 덱):
CardInstance[] memory newCards = new CardInstance[](30);

직접 해보기

  1. gameState의 각 플레이어들을 하나하나 접근하는 for 반복문을 만들게.

  2. 각 플레이어들마다, CardInstance 배열을 newCards라는 이름으로 만들게. 이 배열의 길이는 gameState.playerStates[i].cardsInDeck.length이어야 하네.

  3. 새로운 uintcardCount라는 이름으로 만들고, 그 값으로 0을 넣게.