昨日はコントローラの実装を行った。
今日は人間プレイヤーの実装を行って、実際に遊べるようにしてみる。
Humanクラス
ということで、さっそくコードを。
//============================== // BirdHead //------------------------------ // Human.swift //============================== import Foundation extension NSFileHandle { func readString() -> String { let data = self.availableData let string = NSString(data: data, encoding: NSUTF8StringEncoding)! return string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) } func writeString(string: String) -> Void { let data = string.dataUsingEncoding(NSUTF8StringEncoding)! self.writeData(data) } } class Human: Player { private(set) var name: String private(set) var isCom: Bool init(name: String) { self.name = name self.isCom = false } func select(view: GameInfo.PlayerView) throws -> Action { let stdin = NSFileHandle.fileHandleWithStandardInput() let stdout = NSFileHandle.fileHandleWithStandardOutput() var action: Action! = nil let legalActions = view.legalActions while action == nil { print("hands: \(view.hands)") for i in 0..<legalActions.count { let legalAction = legalActions[i] switch legalAction { case let .Play(cards): print("\(i). play \(cards)") case let .Discard(cards): print("\(i). discard \(cards)") } } print("q. quit") stdout.writeString("> ") let input = stdin.readString() if input == "q" { print("quit.") throw PlayerError.SelectIsCanceled } else { if let selectIndex = Int(input) { if (0 <= selectIndex) && (selectIndex < legalActions.count) { action = legalActions[selectIndex] break } else { print("invalid number.") } } else { print("invalid input.") } } } return action } }
先頭でNSFileHandleを拡張しているのは、標準入出力を簡単に扱えるようにするため。
これについては、変種オセロをSwiftに移植してみた。(その9) - いものやま。を参照。
そして、肝心のHuman#select(_: GameInfo.PlayerView)
では、手札と合法手の一覧を表示させて、合法手からアクションを選ぶようにしている。
このとき、q
が入力されたら、例外を投げて選択をキャンセルするようにもしている。
動作確認
さて、いよいよ動作確認。
まずは、以下のようなコードを用意。
// HumanTest.swift import Foundation let deck = Deck() let game = GameInfo(deck: deck, playerCount: 4) let players: [Player] = [ Human(name: "Player 1"), Human(name: "Player 2"), Human(name: "Player 3"), Human(name: "Player 4"), ] let controller = GameController(gameInfo: game, players: players) controller.output = true do { try controller.start() } catch _ { }
そして、Makefile。
# source files of module SOURCE = Random.swift Deck.swift Action.swift GameInfo.swift \ GameInfoObserver.swift GameController.swift \ Player.swift Human.swift # source files for test TEST_SOURCE = DeckTest.swift ActionTest.swift GameInfoTest.swift HumanTest.swift # test application name (DON'T EDIT) TEST_APP = $(TEST_SOURCE:%.swift=%) # make rules (DON'T EDIT) testbuild: $(TEST_APP) $(TEST_APP): $(SOURCE) $(TEST_APP):%:%.swift cp $< main.swift xcrun -sdk macosx swiftc -o $@ main.swift $(SOURCE) rm main.swift
これでビルドして実行すると、以下のような感じ。
$ ./HumanTest -------------------- deal... ---------- [Player 1] hands: [2, 3, 6, 7, 7, 7, 8, 9, 10, 10] 0. play [2] 1. play [3] 2. play [6] 3. play [7] 4. play [7, 7] 5. play [7, 7, 7] 6. play [8] 7. play [9] 8. play [10] 9. play [10, 10] q. quit > 5 selected action: Play([7, 7, 7]) [Player 2] hands: [3, 4, 4, 4, 5, 6, 7, 10, 11, 11] 0. discard [3, 4, 4] 1. play [7, 10, 11] 2. play [7, 11, 11] 3. play [10, 11, 11] q. quit > 1 selected action: Play([7, 10, 11]) [Player 3] hands: [2, 3, 4, 5, 6, 6, 7, 8, 9, 9] 0. discard [2, 3, 4] q. quit > 0 selected action: Discard([2, 3, 4]) [Player 4] hands: [2, 2, 3, 4, 5, 5, 8, 8, 9, 10] 0. discard [2, 2, 3] q. quit > 0 selected action: Discard([2, 2, 3]) ---------- trick 0 is done. Player 2 takes trick. ---------- [Player 2] hands: [3, 4, 4, 4, 5, 6, 11] 0. play [3] 1. play [4] 2. play [4, 4] 3. play [4, 4, 4] 4. play [5] 5. play [6] 6. play [11] q. quit > 6 selected action: Play([11]) [Player 3] hands: [5, 6, 6, 7, 8, 9, 9] 0. discard [5] q. quit > 0 selected action: Discard([5]) [Player 4] hands: [4, 5, 5, 8, 8, 9, 10] 0. discard [4] q. quit > 0 selected action: Discard([4]) [Player 1] hands: [2, 3, 6, 8, 9, 10, 10] 0. discard [2] q. quit > 0 selected action: Discard([2]) ---------- trick 1 is done. Player 2 takes trick. ---------- [Player 2] hands: [3, 4, 4, 4, 5, 6] 0. play [3] 1. play [4] 2. play [4, 4] 3. play [4, 4, 4] 4. play [5] 5. play [6] q. quit > 5 selected action: Play([6]) [Player 3] hands: [6, 6, 7, 8, 9, 9] 0. play [6] 1. play [7] 2. play [8] 3. play [9] q. quit > 1 selected action: Play([7]) [Player 4] hands: [5, 5, 8, 8, 9, 10] 0. discard [5] 1. play [8] 2. play [9] 3. play [10] q. quit > 2 selected action: Play([9]) [Player 1] hands: [3, 6, 8, 9, 10, 10] 0. discard [3] 1. play [9] 2. play [10] q. quit > 1 selected action: Play([9]) ---------- trick 2 is done. Player 1 takes trick. ---------- [Player 1] hands: [3, 6, 8, 10, 10] 0. play [3] 1. play [6] 2. play [8] 3. play [10] 4. play [10, 10] q. quit > 4 selected action: Play([10, 10]) [Player 2] hands: [3, 4, 4, 4, 5] 0. discard [3, 4] q. quit > 0 selected action: Discard([3, 4]) [Player 3] hands: [6, 6, 8, 9, 9] 0. discard [6, 6] q. quit > 0 selected action: Discard([6, 6]) [Player 4] hands: [5, 5, 8, 8, 10] 0. discard [5, 5] q. quit > 0 selected action: Discard([5, 5]) ---------- trick 3 is done. Player 1 takes trick. ---------- [Player 1] hands: [3, 6, 8] 0. play [3] 1. play [6] 2. play [8] q. quit > 2 selected action: Play([8]) [Player 2] hands: [4, 4, 5] 0. discard [4] q. quit > 0 selected action: Discard([4]) [Player 3] hands: [8, 9, 9] 0. play [8] 1. play [9] q. quit > 1 selected action: Play([9]) [Player 4] hands: [8, 8, 10] 0. discard [8] 1. play [10] q. quit > 1 selected action: Play([10]) ---------- trick 4 is done. Player 4 takes trick. ---------- [Player 4] hands: [8, 8] 0. play [8] q. quit > 0 selected action: Play([8]) [Player 1] hands: [3, 6] 0. discard [3] q. quit > 0 selected action: Discard([3]) [Player 2] hands: [4, 5] 0. discard [4] q. quit > 0 selected action: Discard([4]) [Player 3] hands: [8, 9] 0. play [8] 1. play [9] q. quit > 1 selected action: Play([9]) ---------- trick 5 is done. Player 3 takes trick. ---------- deal is done. last cards: Player 1: 6 Player 2: 5 Player 3: 8 Player 4: 8 ["Player 3", "Player 4"] lose in deal. minus points: Player 1: [] Player 2: [] Player 3: [8] Player 4: [8] -------------------- deal... ---------- 〜省略〜 -------------------- deal... ---------- [Player 3] hands: [3, 3, 6, 6, 8, 9, 9, 10, 10, 11] 0. play [3] 1. play [3, 3] 2. play [6] 3. play [6, 6] 4. play [8] 5. play [9] 6. play [9, 9] 7. play [10] 8. play [10, 10] 9. play [11] q. quit > 6 selected action: Play([9, 9]) [Player 4] hands: [2, 3, 4, 5, 6, 6, 7, 8, 9, 10] 0. discard [2, 3] 1. play [9, 10] q. quit > 1 selected action: Play([9, 10]) [Player 1] hands: [2, 4, 5, 7, 7, 9, 10, 10, 11, 11] 0. discard [2, 4] 1. play [9, 10] 2. play [9, 11] 3. play [10, 10] 4. play [10, 11] 5. play [11, 11] q. quit > 5 selected action: Play([11, 11]) [Player 2] hands: [2, 2, 2, 3, 3, 4, 4, 5, 5, 8] 0. discard [2, 2] q. quit > 0 selected action: Discard([2, 2]) ---------- trick 0 is done. Player 1 takes trick. ---------- [Player 1] hands: [2, 4, 5, 7, 7, 9, 10, 10] 0. play [2] 1. play [4] 2. play [5] 3. play [7] 4. play [7, 7] 5. play [9] 6. play [10] 7. play [10, 10] q. quit > 4 selected action: Play([7, 7]) [Player 2] hands: [2, 3, 3, 4, 4, 5, 5, 8] 0. discard [2, 3] q. quit > 0 selected action: Discard([2, 3]) [Player 3] hands: [3, 3, 6, 6, 8, 10, 10, 11] 0. discard [3, 3] 1. play [8, 10] 2. play [8, 11] 3. play [10, 10] 4. play [10, 11] q. quit > 2 selected action: Play([8, 11]) [Player 4] hands: [2, 3, 4, 5, 6, 6, 7, 8] 0. discard [2, 3] q. quit > 0 selected action: Discard([2, 3]) ---------- trick 1 is done. Player 3 takes trick. ---------- [Player 3] hands: [3, 3, 6, 6, 10, 10] 0. play [3] 1. play [3, 3] 2. play [6] 3. play [6, 6] 4. play [10] 5. play [10, 10] q. quit > 5 selected action: Play([10, 10]) [Player 4] hands: [4, 5, 6, 6, 7, 8] 0. discard [4, 5] q. quit > 0 selected action: Discard([4, 5]) [Player 1] hands: [2, 4, 5, 9, 10, 10] 0. discard [2, 4] 1. play [10, 10] q. quit > 1 selected action: Play([10, 10]) [Player 2] hands: [3, 4, 4, 5, 5, 8] 0. discard [3, 4] q. quit > 0 selected action: Discard([3, 4]) ---------- trick 2 is done. Player 1 takes trick. ---------- [Player 1] hands: [2, 4, 5, 9] 0. play [2] 1. play [4] 2. play [5] 3. play [9] q. quit > 3 selected action: Play([9]) [Player 2] hands: [4, 5, 5, 8] 0. discard [4] q. quit > 0 selected action: Discard([4]) [Player 3] hands: [3, 3, 6, 6] 0. discard [3] q. quit > 0 selected action: Discard([3]) [Player 4] hands: [6, 6, 7, 8] 0. discard [6] q. quit > 0 selected action: Discard([6]) ---------- trick 3 is done. Player 1 takes trick. ---------- [Player 1] hands: [2, 4, 5] 0. play [2] 1. play [4] 2. play [5] q. quit > 2 selected action: Play([5]) [Player 2] hands: [5, 5, 8] 0. play [5] 1. play [8] q. quit > 1 selected action: Play([8]) [Player 3] hands: [3, 6, 6] 0. discard [3] q. quit > 0 selected action: Discard([3]) [Player 4] hands: [6, 7, 8] 0. discard [6] 1. play [8] q. quit > 1 selected action: Play([8]) ---------- trick 4 is done. Player 4 takes trick. ---------- [Player 4] hands: [6, 7] 0. play [6] 1. play [7] q. quit > 1 selected action: Play([7]) [Player 1] hands: [2, 4] 0. discard [2] q. quit > 0 selected action: Discard([2]) [Player 2] hands: [5, 5] 0. discard [5] q. quit > 0 selected action: Discard([5]) [Player 3] hands: [6, 6] 0. discard [6] q. quit > 0 selected action: Discard([6]) ---------- trick 5 is done. Player 4 takes trick. ---------- deal is done. last cards: Player 1: 4 Player 2: 5 Player 3: 6 Player 4: 6 ["Player 4", "Player 3"] lose in deal. minus points: Player 1: [] Player 2: [7] Player 3: [8, 7, 6] Player 4: [8, 6, 5, 6] -------------------- game ended. total minus points: Player 1: 0 Player 2: 7 Player 3: 21 Player 4: 25 ["Player 4"] lose.
全員人間プレイヤーにしているので手札が丸見えだけど、ちゃんと遊べているのが分かると思う。
今日はここまで!