fix Swift tests

This commit is contained in:
Dan Crosby
2017-09-17 18:24:13 -07:00
parent 72150240d2
commit 6a28302b51
7 changed files with 63 additions and 56 deletions
+7 -4
View File
@@ -1,20 +1,24 @@
BUG: action points not updating on new turn (because no update on start turn)
BUG: rest button not updating
PERF: deterministic vs non-deterministic MonteCarloTreeNodes
PERF: trylock and move on rather than waiting during selection
PERF: multiple random playthroughs at a time
PERF: simple weights for terrain?
PERF: cache dirty state of game status
PERF: improve 2-tile-away performance
PERF: (possibly big) combine Move options in AI GetActions
PERF: (possibly big) combine Move options in AI GetActions with barriers around attacks etc
PERF: (possibly big) test perf of recursive Simulate without parent pointers
PERF: further special-case root MonteCarloTreeNode to not call GetAvailableActions
PERF: MapIndex as 8-bit?
PERF: Replace HeroSPtr with unique_ptr?
PERF: Don't track history in simulation games
PERF: specialize small ints in Croissant
HEALTH: add tests for IsLegal
HEALTH: add tests for most Engine interface commands
HEALTH: no HeroSPtrs in public Engine methods
* HEALTH: no Hero references in public Engine methods, only HeroInfo
HEALTH: make PostActionUnchecked available only in game copies
HEALTH: fix Swift tests
RULES: no archery over mountains
RULES: no movement after moving adjacent enemy
@@ -23,4 +27,3 @@ RULES: flanking, except in castles
PLAYABILITY: map editor
SAFETY: make PostActionUnchecked available only in game copies
+1 -23
View File
@@ -57,27 +57,5 @@ public struct Hero : Codable {
public let battalion : Battalion
public let actionPoints : ActionPoints
/*
init(heroId: HeroId, playerId: PlayerId, name: String, strength: Double, agility: Double, constitution: Double,
charisma: Double, intelligence: Double, wisdom: Double, integrity: Double, ambition: Double,
gregariousness: Double, bravery: Double, vigor: Double, mage: Bool, location: Coordinates, battalion: Battalion, actionPoints: ActionPoints) {
self.heroId = heroId
self.playerId = playerId
self.name = name
self.strength = strength
self.agility = agility
self.constitution = constitution
self.charisma = charisma
self.intelligence = intelligence
self.wisdom = wisdom
self.integrity = integrity
self.ambition = ambition
self.gregariousness = gregariousness
self.bravery = bravery
self.vigor = vigor
self.mage = mage
self.location = location
self.battalion = battalion
self.actionPoints = actionPoints
}*/
}
@@ -333,7 +333,7 @@ class CroissantDecoderTests: XCTestCase {
data.append(stringObject: "player") // key
data.append(hexString: "42532A") // value, 21290
data.append(stringObject: "actor") // key
data.append(hexString: "4312D687") // value, 1234567
data.append(hexString: "4204D2") // value, 1234567
data.append(stringObject: "direction") // key
data.append(hexString: "4101") // value, 1
data.append(stringObject: "type") // key
@@ -342,7 +342,7 @@ class CroissantDecoderTests: XCTestCase {
data.append(stringObject: "Attack east") // value
let decoded = try! ActionDescriptor(from: try! CroissantDecoder(withData: data))
let expectedAction = ActionDescriptor(player: 21290, actor: 1234567, direction: .east, type: .meleeAttack, description: "Attack east")
let expectedAction = ActionDescriptor(player: 21290, actor: 1234, direction: .east, target: nil, type: .meleeAttack, description: "Attack east")
XCTAssertEqual(decoded, expectedAction)
}
@@ -352,7 +352,7 @@ class CroissantDecoderTests: XCTestCase {
data.append(stringObject: "player") // key
data.append(hexString: "42532A") // value, 21290
data.append(stringObject: "actor") // key
data.append(hexString: "4312D687") // value, 1234567
data.append(hexString: "4204D2") // value, 1234567
data.append(stringObject: "direction") // key
data.append(hexString: "4101") // value, 1
data.append(stringObject: "type") // key
@@ -361,7 +361,7 @@ class CroissantDecoderTests: XCTestCase {
data.append(stringObject: "Attack east") // value
let decoded = try! [ActionDescriptor](from: try! CroissantDecoder(withData: data))
let expectedActionArray = [ActionDescriptor(player: 21290, actor: 1234567, direction: .east, type: .meleeAttack, description: "Attack east")]
let expectedActionArray = [ActionDescriptor(player: 21290, actor: 1234, direction: .east, target: nil, type: .meleeAttack, description: "Attack east")]
XCTAssertEqual(decoded, expectedActionArray)
}
@@ -371,14 +371,14 @@ class CroissantDecoderTests: XCTestCase {
data.append(stringObject: "player") // key
data.append(hexString: "42532A") // value, 21290
data.append(stringObject: "type") // key
data.append(hexString: "4102") // value, 2 (end turn)
data.append(hexString: "4104") // value, 4 (end turn)
data.append(stringObject: "description") // key
data.append(stringObject: "End turn") // value
data.append(hexString: "0x65") // 5-element map
data.append(stringObject: "player") // key
data.append(hexString: "42532A") // value, 21290
data.append(stringObject: "actor") // key
data.append(hexString: "4312D687") // value, 1234567
data.append(hexString: "4204D2") // value, 1234567
data.append(stringObject: "direction") // key
data.append(hexString: "4101") // value, 1
data.append(stringObject: "type") // key
@@ -389,9 +389,9 @@ class CroissantDecoderTests: XCTestCase {
let decoder = try CroissantDecoder(withData: data)
let decoded = try [ActionDescriptor](from: decoder)
let heroAction = ActionDescriptor(player: 21290, actor: 1234567, direction: .east, type: .meleeAttack, description: "Attack east")
let endTurnAction = ActionDescriptor(player: 21290, actor: nil, direction: nil, type: .endTurn, description: "End turn")
let expectedActions = AvailableActions([endTurnAction, heroAction])
let heroAction = ActionDescriptor(player: 21290, actor: 1234, direction: .east, target: nil, type: .meleeAttack, description: "Attack east")
let endTurnAction = ActionDescriptor(player: 21290, actor: nil, direction: nil, target: nil, type: .endTurn, description: "End turn")
let expectedActions = [endTurnAction, heroAction]
XCTAssertEqual(decoded, expectedActions)
}
+35 -14
View File
@@ -11,6 +11,9 @@ import XCTest
class PlayerGameModelTest: XCTestCase {
class PlayerClientInterfaceMock : PlayerClientInterface {
func run() {
}
let playerId: PlayerId
var hexMap : HexMap? = HexMap(rowCount: 2, columnCount: 2, oddRowsShorter: false, terrainValues: [.plains, .mountain, .castle, .forest])
var history = TurnHistory()
@@ -18,10 +21,11 @@ class PlayerGameModelTest: XCTestCase {
var allHeroes : [Hero]?
var oneHero : Hero?
var myTurn = false
var availableActions : AvailableActions?
var availableActions : [ActionDescriptor]?
var actionResult : ActionResult?
private(set) var updateCallback : ((TurnHistoryEntry?) -> Void)?
private(set) var actionCallback : ((TurnHistoryEntry?) -> Void)?
private(set) var gameOverCallback : ((GameStatus?) -> Void)?
func getAllHeroes(_ handler: @escaping ([Hero]?) -> Void) {
handler(allHeroes)
@@ -35,7 +39,7 @@ class PlayerGameModelTest: XCTestCase {
handler(myTurn)
}
func getAvailableActions(_ handler: @escaping (AvailableActions?) -> Void) {
func getAvailableActions(_ handler: @escaping ([ActionDescriptor]?) -> Void) {
handler(availableActions)
}
@@ -47,8 +51,9 @@ class PlayerGameModelTest: XCTestCase {
handler(actionResult)
}
func registerUpdateCallback(_ updateCallback: @escaping (TurnHistoryEntry?) -> Void) {
self.updateCallback = updateCallback
func register(actionCallback: @escaping (TurnHistoryEntry?) -> Void, gameOverCallback: @escaping (GameStatus?) -> Void) {
self.actionCallback = actionCallback
self.gameOverCallback = gameOverCallback
}
init(withPlayerId: PlayerId) {//, hexMap: HexMap, history: TurnHistory) {
@@ -57,6 +62,16 @@ class PlayerGameModelTest: XCTestCase {
}
class ViewControllerMock : GenericViewController {
var endTurnEnabled: Bool = false
var restEnabled: Bool = false
var playerTotalSize: Int32 = 1
var opponentTotalSize: Int32 = 2
var gameStatus: String = "Game running"
var model: PlayerGameModel!
var selectedHero: Hero?
var isPlayersTurn: Bool = false
@@ -107,17 +122,19 @@ class PlayerGameModelTest: XCTestCase {
}
func testRegistersUpdateCallback() {
XCTAssertNil(interface.updateCallback)
XCTAssertNil(interface.actionCallback)
model = PlayerGameModel(withClientInterface: interface, viewController: controller)
XCTAssertNotNil(interface.updateCallback)
model.ready()
XCTAssertNotNil(interface.actionCallback)
}
func testAllHeroes_containsAllHeroes() {
interface.allHeroes = [HERO1, HERO2]
XCTAssertTrue(controller.placedHeroIds.isEmpty)
model = PlayerGameModel(withClientInterface: interface, viewController: controller)
model.ready()
assertAfterMainQueueCallbacks {
XCTAssertEqual(controller.placedHeroIds.count, 2)
XCTAssertGreaterThanOrEqual(controller.placedHeroIds.count, 2)
XCTAssertTrue(controller.placedHeroIds.contains(HERO1.heroId))
XCTAssertTrue(controller.placedHeroIds.contains(HERO2.heroId))
}
@@ -126,9 +143,10 @@ class PlayerGameModelTest: XCTestCase {
func testUpdateCallback_removedHeroes_removesHeroes() {
interface.allHeroes = [HERO1, HERO2]
model = PlayerGameModel(withClientInterface: interface, viewController: controller)
let newTurnHistoryEntry = TurnHistoryEntry(actionId: 123, message: "a turn entry", changedHeroes: nil, removedHeroes: [HERO1.heroId], nextPlayer: 0)
model.ready()
let newTurnHistoryEntry = TurnHistoryEntry(actionId: 123, message: "a turn entry", changedHeroes: nil, removedHeroes: [HERO1.heroId], nextPlayer: 0, nextRound: 1)
XCTAssertTrue(controller.removedHeroCoordinates.isEmpty)
interface.updateCallback!(newTurnHistoryEntry)
interface.actionCallback!(newTurnHistoryEntry)
assertAfterMainQueueCallbacks {
XCTAssertEqual(controller.removedHeroCoordinates.count, 1)
XCTAssertEqual(controller.removedHeroCoordinates.first!, HERO1.location)
@@ -142,12 +160,15 @@ class PlayerGameModelTest: XCTestCase {
func testUpdateCallback_becomesMyTurn_selectsHero() {
interface.allHeroes = [HERO1, HERO2]
model = PlayerGameModel(withClientInterface: interface, viewController: controller)
model.ready()
XCTAssertNil(controller.selectedHero)
let newTurnHistoryEntry = TurnHistoryEntry(actionId: 123, message: "other player finished", changedHeroes: nil, removedHeroes: nil, nextPlayer: PLAYER_ID)
interface.availableActions = [ActionDescriptor(player: PLAYER_ID, actor: HERO1.heroId, direction: HexMap.Direction.east, type: .move, description: "move east")]
interface.updateCallback!(newTurnHistoryEntry)
let newTurnHistoryEntry = TurnHistoryEntry(actionId: 123, message: "other player finished", changedHeroes: nil, removedHeroes: nil, nextPlayer: PLAYER_ID, nextRound: 1)
interface.availableActions = [ActionDescriptor(player: PLAYER_ID, actor: HERO1.heroId, direction: HexMap.Direction.east, target: nil, type: .move, description: "move east")]
interface.actionCallback!(newTurnHistoryEntry)
assertAfterMainQueueCallbacks {
XCTAssertEqual(controller.selectedHero!.heroId, HERO1.heroId)
assertAfterMainQueueCallbacks {
XCTAssertEqual(controller.selectedHero!.heroId, HERO1.heroId)
}
}
}
+2
View File
@@ -32,6 +32,7 @@ let HERO1 = Hero(heroId: 123,
gregariousness: 10,
bravery: 5,
vigor: 4,
volleys: 5,
mage: false,
location: Coordinates(row: MapIndex(0), column: MapIndex(0)),
battalion: BATTALION1,
@@ -58,6 +59,7 @@ let HERO2 = Hero(heroId: 9998,
gregariousness: 100,
bravery: 7,
vigor: 99,
volleys: 9,
mage: true,
location: Coordinates(row: MapIndex(1), column: MapIndex(0)),
battalion: BATTALION2,
+4 -3
View File
@@ -140,6 +140,7 @@ ShardokResult ShardokEngine::PostActionUnchecked(ActionDescriptor action, bool g
if (actingHero->IsDestroyed()) {
removedHeroes.push_back(heroId);
hexMap->RemoveOccupant(actingHero->GetLocation());
allHeroes[heroId].reset();
} else {
changedHeroes.push_back(actingHero->GetInfo());
}
@@ -182,8 +183,8 @@ AvailableActions ShardokEngine::GetAvailableActions(PlayerId playerId) {
actions.reserve(heroesForPlayer[playerId].size() * 6 + 2);
for (HeroSPtr hero : heroesForPlayer[playerId]) {
if (hero == nullptr) continue;
HeroId heroId = hero->GetId();
if (hero->IsDestroyed()) continue;
if (hero->GetRemainingActionPoints() < MIN_ACTION_POINTS_TO_ACT) continue;
Coords currentCoords = hero->GetLocation();
@@ -229,6 +230,7 @@ GameStatus ShardokEngine::UpdateGameStatus(bool atEndOfRound) const {
bool attackerStanding = false;
for (PlayerId attackerId = 0; attackerId < numAttackers; attackerId++) {
for (HeroSPtr hero : heroesForPlayer[attackerId]) {
if (hero == nullptr) continue;
if (hero->GetBattalion()->GetSize() > 0 ||
hero->GetVigor() > 0) {
attackerStanding = true;
@@ -246,8 +248,7 @@ GameStatus ShardokEngine::UpdateGameStatus(bool atEndOfRound) const {
bool defenderStanding = false;
for (PlayerId defenderId = numAttackers; defenderId < numAttackers + numDefenders; defenderId++) {
for (HeroSPtr hero : heroesForPlayer[defenderId]) {
if (hero->GetBattalion()->GetSize() > 0 ||
hero->GetVigor() > 0) {
if (hero != nullptr) {
defenderStanding = true;
break;
}
+5 -3
View File
@@ -26,7 +26,7 @@ private:
const PlayerId numDefenders;
const HeroIdList maxHeroIdForPlayer;
const HeroList allHeroes; // HeroId is the index
HeroList allHeroes; // HeroId is the index
const HexMapSPtr hexMap;
vector<const HeroList> heroesForPlayer;
@@ -58,7 +58,9 @@ protected:
if (gameStatus.state == GameStatus::gameRunning) {
for (HeroSPtr hero : heroesForPlayer[currentPlayer]) {
hero->SetRemainingActionPoints(hero->GetMaxActionPoints());
if (hero != nullptr) {
hero->SetRemainingActionPoints(hero->GetMaxActionPoints());
}
}
}
}
@@ -124,7 +126,7 @@ public:
throw ShardokException("Trying to end turn for player " + std::to_string(pid) + ", but turn belongs to " + std::to_string(currentPlayer));
}
for (HeroSPtr hero : heroesForPlayer[currentPlayer]) {
if (!hero->IsDestroyed()) {
if (hero != nullptr) {
hero->Rest();
}
}