From bc0fbd1ffa30c80fcb36b38257854059678e8acb Mon Sep 17 00:00:00 2001 From: Curt Sellmer Date: Thu, 16 May 2024 13:00:52 -0500 Subject: [PATCH] feat: Add readability improvements We now show zone numbers with space names. We now pause to allow the user to see what the Bot has done and require the user to press enter to continue. fixes #6 --- src/main/scala/coltwi/Bot.scala | 51 ++++++--- src/main/scala/coltwi/Cards.scala | 77 +++++++------ src/main/scala/coltwi/ColonialTwilight.scala | 113 +++++++++++++------ src/main/scala/coltwi/Human.scala | 83 +++++++------- 4 files changed, 195 insertions(+), 129 deletions(-) diff --git a/src/main/scala/coltwi/Bot.scala b/src/main/scala/coltwi/Bot.scala index 7976db5..5590ffa 100644 --- a/src/main/scala/coltwi/Bot.scala +++ b/src/main/scala/coltwi/Bot.scala @@ -114,6 +114,7 @@ object Bot { // exist in the original gamestate. def showLogEntries(orig: GameState, updated: GameState): Unit = { updated.history.drop(orig.history.size) foreach println + pause() } // In order for the Bot to play an event that is not marked for FLN play, @@ -420,6 +421,7 @@ object Bot { removeToAvailable(name, pieces) if (replace) placePieces(name, Pieces(hiddenGuerrillas = 1)) + pause() } } } @@ -455,11 +457,13 @@ object Bot { for (sp <- primary) { activateHiddenGuerrillas(sp.name, 1) increaseResources(Fln, 1) + pause() } if (game.resources(Fln) == 0) for (sp <- secondary) { activateHiddenGuerrillas(sp.name, 1) increaseResources(Fln, 1) + pause() } } } @@ -480,6 +484,7 @@ object Bot { log(separator()) log(s"FLN chooses: ${Pass}") performPass(Fln) + pause() Right(Pass) } } @@ -604,7 +609,7 @@ object Bot { if (isFree || game.resources(Fln) > 0) { terrorized += target.name log() - log(s"$Fln executes Terror operation: ${target.name}") + log(s"$Fln executes Terror operation: ${target.nameAndZone}") if (isFree) log(s"Terror is free in city because '${CapEffectiveBomber}' is in play") else @@ -614,7 +619,7 @@ object Bot { addTerror(target.name, 1) if (!momentumInPlay(MoIntimidation)) setSupport(target.name, Neutral) - + pause() nextTerror() } } @@ -669,16 +674,17 @@ object Bot { var sp = game.getSpace(name) if (ambush) { log() - log(s"$Fln executes Attack operation with ambush: $name") + log(s"$Fln executes Attack operation with ambush: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) if (!capabilityInPlay(CapFlnCommandos)) activateHiddenGuerrillas(name, 1) removeLosses(name, attackLosses(sp.pieces, ambush)) + pause() } else { log() - log(s"$Fln executes Attack operation: $name") + log(s"$Fln executes Attack operation: ${sp.nameAndZone}") decreaseResources(Fln, 1) activateHiddenGuerrillas(name, sp.hiddenGuerrillas) sp = game.getSpace(name) @@ -696,6 +702,7 @@ object Bot { placePieces(name, Pieces(hiddenGuerrillas = 1)) } } + pause() } } @@ -928,16 +935,17 @@ object Bot { if (force && haveAResource()) { logRallyChoice() log() - log(s"$Fln executes Rally operation to allow agitation: ${sp.name}") + log(s"$Fln executes Rally operation to allow agitation: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) rallySpaces += sp.name + pause() } case PlaceBase => if (haveAResource()) { logRallyChoice() log() - log(s"$Fln executes Rally operation: ${sp.name}") + log(s"$Fln executes Rally operation: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) val numActive = 2 min sp.activeGuerrillas @@ -946,6 +954,7 @@ object Bot { placePieces(sp.name, Pieces(flnBases = 1), logControl = false) logControlChange(sp, game.getSpace(sp.name)) rallySpaces += sp.name + pause() } case PlaceGuerrillas => @@ -965,32 +974,35 @@ object Bot { if (haveAResource()) { logRallyChoice() log() - log(s"$Fln executes Rally operation to allow agitation: ${sp.name}") + log(s"$Fln executes Rally operation to allow agitation: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) rallySpaces += sp.name + pause() } case GuerrillasToPlace(0, Nil) => // Flip any active if (numToPlace == 0 && sp.activeGuerrillas > 0 && haveAResource()) { logRallyChoice() log() - log(s"$Fln executes Rally operation: ${sp.name}") + log(s"$Fln executes Rally operation: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) hideActiveGuerrillas(sp.name, sp.activeGuerrillas) rallySpaces += sp.name + pause() } case guerrillas => // Place guerrillas from sources if (haveAResource()) { logRallyChoice() log() - log(s"$Fln executes Rally operation: ${sp.name}") + log(s"$Fln executes Rally operation: ${sp.nameAndZone}") if (!turnState.freeOperation) decreaseResources(Fln, 1) placeGuerrillas(sp.name, guerrillas) rallySpaces += sp.name + pause() } } case _ => @@ -1013,6 +1025,7 @@ object Bot { decreaseResources(Fln, 1) increaseFranceTrack(1) shiftedFranceTrack = true + pause() } val supportSectorCandidates = spaceNames(game.spaces filter onlyIn filter (sp => (!hasRallied(sp.name) && sectorsAtSupport(sp)))) doRallies(supportSectorCandidates, PlaceGuerrillas, SupportSectorPriorities) @@ -1063,10 +1076,11 @@ object Bot { agitateSpace foreach { name => val sp = game.getSpace(name) log() - log(s"$Fln agitates in $name") + log(s"$Fln agitates in ${sp.nameAndZone}") decreaseResources(Fln, costToAgitate(sp)) removeTerror(name, sp.terror) decreaseSupport(name, 1) + pause() } } @@ -1404,9 +1418,9 @@ object Bot { val guerrillas = path.marchers(num, marchType.hiddenOnly, !(path.sourceHasBase || activates)) log() if (path.isAdjacent) - log(s"$Fln marches adjacent from ${path.source} to ${path.dest}") + log(s"$Fln marches adjacent from ${displaySpace(path.source)} to ${displaySpace(path.dest)}") else { - log(s"$Fln marches from ${path.source} to ${path.dest} via: ${andList(path.spaces.tail.init)}") + log(s"$Fln marches from ${displaySpace(path.source)} to ${displaySpace(path.dest)} via: ${andList(path.spaces.tail.init)}") if (guerrillas.hiddenGuerrillas > 0 && activates) { val activateSpace = path.activatedBySpace(num).get log(s"Entering $activateSpace activates the hidden guerrillas") @@ -1710,19 +1724,22 @@ object Bot { if (candidates.nonEmpty) { agitatedOnce = true val sp = topPriority(candidates, priorities) - log(s"\nFLN agitates: ${sp.name}") + log(s"\nFLN agitates: ${sp.nameAndZone}") log(separator()) val cost = sp.terror + maxShift(sp) decreaseResources(Fln, cost) removeTerror(sp.name, sp.terror) decreaseSupport(sp.name, maxShift(sp)) + pause() nextAgitate(resRemaining - cost, agitated + sp.name) } } log("\nFLN agitation") nextAgitate(game.resources(Fln) * 2 / 3, Set.empty) - if (!agitatedOnce) + if (!agitatedOnce) { log("FLN does not agitate any spaces") + pause() + } } // The FLN player may now move any Guerrillas from any space or spaces within a given Wilaya, @@ -1782,6 +1799,7 @@ object Bot { val a = num min sp.activeGuerrillas val h = (num - a) min sp.hiddenGuerrillas redeployPieces(Pieces(hiddenGuerrillas = h, activeGuerrillas = a), srcName, destName) + pause() redeployed = true } } @@ -1798,6 +1816,7 @@ object Bot { val newDestMap = destMap + (srcName -> (destMap(srcName) + 1)) val newRedeployments = redeployments + (destName -> newDestMap) redeployGuerrillas(newSrcs, newDests, newRedeployments) + pause() } } @@ -1811,8 +1830,10 @@ object Bot { else for (wilaya <- ALL_WILAYAS) redeployGuerrillas(getSources(game.wilayaSpaces(wilaya)), getDests(game.wilayaSpaces(wilaya))) - if (!redeployed) + if (!redeployed) { log("FLN does not redeploy any guerrillas") + pause() + } } } \ No newline at end of file diff --git a/src/main/scala/coltwi/Cards.scala b/src/main/scala/coltwi/Cards.scala index 35c072a..cf16f08 100644 --- a/src/main/scala/coltwi/Cards.scala +++ b/src/main/scala/coltwi/Cards.scala @@ -114,7 +114,7 @@ object Cards { println(s"\nFrench police in the available box: ${game.frenchPoliceAvailable}") askMenu(choices).head match { case "space" => - val name = askCandidate("Which space: ", candidates) + val name = askSpace("Which space: ", candidates) val num = askInt("How many French Police", 0, game.frenchPoliceAvailable) placePieces(name, Pieces(frenchPolice = num)) nextSpace(remaining - 1, candidates filterNot (_ == name)) @@ -204,9 +204,9 @@ object Cards { num } else { - val name = askCandidate("\nSelect space to remove french cubes: ", spaceCandidates(_.frenchCubes > 0)) + val name = askSpace("\nSelect space to remove french cubes: ", spaceCandidates(_.frenchCubes > 0)) val sp = game.getSpace(name) - val num = askInt(s"Remove how many total cubes from $name", 0, sp.frenchCubes min remaining) + val num = askInt(s"Remove how many total cubes from ${sp.nameAndZone}", 0, sp.frenchCubes min remaining) if (num > 0) { val cubes = askPieces(sp.pieces, num, FRENCH_CUBES) removeToOutOfPlay(name, cubes) @@ -271,9 +271,9 @@ object Cards { def removeGuerrillas(remaining: Int): Unit = { val candidates = wilayaCandidates(wilaya)(_.totalGuerrillas > 0) if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate(s"Select space in Wilaya $wilaya: ", candidates) + val name = askSpace(s"Select space in Wilaya $wilaya: ", candidates) val sp = game.getSpace(name) - val num = askInt(s"Remove how many guerrillas from $name", 0, remaining min sp.totalGuerrillas) + val num = askInt(s"Remove how many guerrillas from ${sp.nameAndZone}", 0, remaining min sp.totalGuerrillas) if (num > 0) { val guerrillas = askPieces(sp.pieces, num, GUERRILLAS) removeToAvailable(name, guerrillas) @@ -323,9 +323,9 @@ object Cards { def removeGuerrillas(remaining: Int): Unit = { val candidates = wilayaCandidates(wilaya)(_.totalGuerrillas > 0) if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate(s"Select space in Wilaya $wilaya: ", candidates) + val name = askSpace(s"Select space in Wilaya $wilaya: ", candidates) val sp = game.getSpace(name) - val num = askInt(s"Remove how many guerrillas from $name", 0, remaining min sp.totalGuerrillas) + val num = askInt(s"Remove how many guerrillas from ${sp.nameAndZone}", 0, remaining min sp.totalGuerrillas) if (num > 0) { val guerrillas = askPieces(sp.pieces, num, GUERRILLAS) removeToAvailable(name, guerrillas) @@ -391,8 +391,11 @@ object Cards { def affectNeutral(candidates: List[String], remaining: Int): Unit = { if (remaining > 0 && candidates.nonEmpty) { println() - val name = askCandidate("\nSelect a non-terrorized neutral space: ", candidates) - val choices = List("support" -> s"Set $name to Support", "oppose" -> s"Set $name to Opposition") + val name = askSpace("\nSelect a non-terrorized neutral space: ", candidates) + val choices = List( + "support" -> s"Set ${displaySpace(name)} to Support", + "oppose" -> s"Set ${displaySpace(name)} to Opposition" + ) setSupport(name, if (askMenu(choices).head == "support") Support else Oppose) affectNeutral(candidates filterNot (_ == name), remaining - 1) } @@ -611,7 +614,7 @@ object Cards { (role: Role) => { // Heads broken: Set 1 selected City to Neutral. // Add commitment = population of city - val name = askCandidate("\nSelect a city: ", algerianCandidates(sp => sp.isCity)) + val name = askSpace("\nSelect a city: ", algerianCandidates(sp => sp.isCity)) val sp = game.getSpace(name) setSupport(sp.name, Neutral) increaseCommitment(sp.population) @@ -650,10 +653,10 @@ object Cards { def removePieces(remaining: Int, types: Seq[PieceType], desc: String): Unit = { val candidates = spaceCandidates(_.totalOf(types) > 0) if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate(s"\nSelect space to remove $desc: ", candidates) + val name = askSpace(s"\nSelect space to remove $desc: ", candidates) val sp = game.getSpace(name) val most = remaining min sp.totalOf(types) - val num = askInt(s"Remove how many $desc from $name", 0, most) + val num = askInt(s"Remove how many $desc from ${sp.nameAndZone}", 0, most) val pieces = askPieces(sp.pieces, num, types) removeToAvailable(name, pieces) removePieces(remaining - num, types, desc) @@ -737,7 +740,7 @@ object Cards { def nextSpace(remaining: Int): Unit = { val candiates = algerianCandidates(canAffect) if (remaining > 0 && candiates.nonEmpty) { - val name = askCandidate("\nSelect space: ", candiates) + val name = askSpace("\nSelect space: ", candiates) setSupport(name, Support) nextSpace(remaining - 1) } @@ -768,10 +771,10 @@ object Cards { def removeGuerrillas(remaining: Int): Unit = { val candidates = spaceCandidates(_.totalGuerrillas > 0) if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate(s"\nSelect space to remove guerrillas: ", candidates) + val name = askSpace(s"\nSelect space to remove guerrillas: ", candidates) val sp = game.getSpace(name) val most = remaining min sp.totalGuerrillas - val num = askInt(s"Remove how many guerrillas from $name", 0, most) + val num = askInt(s"Remove how many guerrillas from ${sp.nameAndZone}", 0, most) val pieces = askPieces(sp.pieces, num, GUERRILLAS) removeToAvailable(name, pieces) removeGuerrillas(remaining - num) @@ -895,7 +898,7 @@ object Cards { log(s"There are no available terror markers. The event has no effect") else { def nextMarker(remaining: Int): Unit = if (remaining > 0) { - val name = askCandidate("\nSelect space for terror marker: ", spaceNames(game.algerianSpaces).sorted) + val name = askSpace("\nSelect space for terror marker: ", spaceNames(game.algerianSpaces).sorted) decreaseResources(Gov, 1) addTerror(name, 1) setSupport(name, Neutral) @@ -1056,7 +1059,7 @@ object Cards { } choice match { case "commit" => increaseCommitment(1) - case "space" => setSupport(askCandidate("\nSelect space: ", candidates), Support) + case "space" => setSupport(askSpace("\nSelect space: ", candidates), Support) case _ => log("The event has no effect") } }, @@ -1098,7 +1101,7 @@ object Cards { else { val candidates = spaceCandidates(_.totalGuerrillas > 0) if (candidates.nonEmpty) { - val name = askCandidate("\nSelect space to remove guerrilla: ", candidates) + val name = askSpace("\nSelect space to remove guerrilla: ", candidates) val sp = game.getSpace(name) val guerrilla = askPieces(sp.pieces, 1, GUERRILLAS) removeToCasualties(name, guerrilla) @@ -1157,7 +1160,7 @@ object Cards { // Harsh terrain: Select 2 Mountain spaces with no FLN Base. // Remove all guerrillas there to available. def nextSpace(remaining: Int, candidates: List[String]): Unit = if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate("\nSelect mountain space with guerrillas and no FLN base: ", candidates) + val name = askSpace("\nSelect mountain space with guerrillas and no FLN base: ", candidates) removeToAvailable(name, game.getSpace(name).only(GUERRILLAS)) nextSpace(remaining - 1, candidates filterNot (_ == name)) } @@ -1184,7 +1187,7 @@ object Cards { if (num > total) Nil else { - val name = askCandidate(s"\nSelect ${ordinal(num)} coastal space: ", candidates) + val name = askSpace(s"\nSelect ${ordinal(num)} coastal space: ", candidates) name :: selectSpaces(num + 1, total, candidates filterNot (_ == name)) } } @@ -1199,7 +1202,7 @@ object Cards { ).flatten val avail = sourceCandidates.sortBy(_.name) map { sp => - s"${sp.name} (${sp.pieces.only(CUBES) - Human.movingGroups(sp.name)})" + s"${sp.nameAndZone} (${sp.pieces.only(CUBES) - Human.movingGroups(sp.name)})" } val moved = Human.movingGroups.toList.sortBy(_._1) map { case (n, p) => s"$n ($p)"} println("\n") @@ -1217,11 +1220,11 @@ object Cards { case "cube" => val savedState = game try { - val source = askCandidate(s"\nSelect source space: ", spaceNames(sourceCandidates).sorted) - val dest = askCandidate(s"Select destination space: ", (selectedNames filterNot (_ == source))) + val source = askSpace(s"\nSelect source space: ", spaceNames(sourceCandidates).sorted) + val dest = askSpace(s"Select destination space: ", (selectedNames filterNot (_ == source))) val sp = game.getSpace(source) val most = (6 - totalMoved) min movableCubes(sp).total - val num = askInt(s"Move how many cubes from $source to $dest", 0, most) + val num = askInt(s"Move how many cubes from ${displaySpace(sp)} to ${displaySpace(dest)}", 0, most) val p = askPieces(movableCubes(sp), num, CUBES) movePieces(p, source, dest) Human.movingGroups.add(dest, p) @@ -1287,7 +1290,7 @@ object Cards { if (num > total) Nil else { - val name = askCandidate(s"\nSelect ${ordinal(num)} city: ", candidates) + val name = askSpace(s"\nSelect ${ordinal(num)} city: ", candidates) name :: selectCities(num + 1, total, candidates filterNot (_ == name)) } } @@ -1362,9 +1365,9 @@ object Cards { if (candidates.isEmpty) log("The event has no effect") else { - val name = askCandidate("\nSelect sector with guerrillas: ", candidates) + val name = askSpace("\nSelect sector with guerrillas: ", candidates) val guerrillas = askPieces(game.getSpace(name).pieces, 3, GUERRILLAS, - Some(s"Select guerrillas to remove from $name")) + Some(s"Select guerrillas to remove from ${displaySpace(name)}")) removeToAvailable(name, guerrillas) val police = askPiecesToPlace(name, List(AlgerianPolice), guerrillas.total) placePieces(name, police) @@ -1470,16 +1473,16 @@ object Cards { // Self-purge: Activate all Guerrillas in 1 spce in Algeria, // roll 1d6. If result <= to total guerrillas in the space, // remove two guerrillas to casualties. - val name = askCandidate("Select space in Algeria: ", spaceNames(game.algerianSpaces)) + val name = askSpace("Select space in Algeria: ", spaceNames(game.algerianSpaces)) activateHiddenGuerrillas(name, game.getSpace(name).hiddenGuerrillas) val sp = game.getSpace(name) val die = dieRoll - log(s"\nThere are ${activeG(sp.activeGuerrillas)} in $name") + log(s"\nThere are ${activeG(sp.activeGuerrillas)} in ${sp.nameAndZone}") log(s"Die roll: $die") if (die <= sp.totalGuerrillas) removeToCasualties(name, Pieces(activeGuerrillas = 2 min sp.activeGuerrillas)) else - log(s"No guerrillas are removed from $name") + log(s"No guerrillas are removed from ${sp.nameAndZone}") }, (role: Role) => () )), @@ -1505,7 +1508,7 @@ object Cards { new Bot.BooleanPriority[Space]("Support Space", _.isSupport)) val name = if (role == Gov) - askCandidate("\nSelect sector: ", algerianCandidates(_.isSector)) + askSpace("\nSelect sector: ", algerianCandidates(_.isSector)) else // role == Fln Bot.topPriority(game.algerianSpaces filter stripeyHoleUnshaded, priorities).name @@ -1567,16 +1570,16 @@ object Cards { // (may be Underground, but Guerrillas before bases) to Available // if any there. if (role == Gov) { - val destName = askCandidate("\nSelect mountain sector: ", algerianCandidates(_.isMountains)) + val destName = askSpace("\nSelect mountain sector: ", algerianCandidates(_.isMountains)) val dest = game.getSpace(destName) val withMovableTroops = (sp: Space) => sp.name != destName && sp.frenchTroops > 0 val movableTroops = game.totalOnMap(_.frenchTroops) - dest.frenchTroops val mostTroops = 4 min movableTroops - val total = askInt(s"Move how many French troops to $destName", 0, mostTroops) + val total = askInt(s"Move how many French troops to ${dest.nameAndZone}", 0, mostTroops) def moveTroops(remaining: Int): Unit = if (remaining > 0) { - val name = askCandidate("\nSelect space with French troops: ", algerianCandidates(withMovableTroops)) + val name = askSpace("\nSelect space with French troops: ", algerianCandidates(withMovableTroops)) val sp = game.getSpace(name) - val num = askInt(s"Move how many French Troops out of $name", 0, remaining min sp.frenchTroops) + val num = askInt(s"Move how many French Troops out of ${sp.nameAndZone}", 0, remaining min sp.frenchTroops) movePieces(Pieces(frenchTroops = num), name, destName) moveTroops(remaining - num) } @@ -1634,7 +1637,7 @@ object Cards { def placeBases(remaining: Int, oop: Boolean): Unit = if (remaining > 0) { val prompt = s"\nSelect space for base from ${if (oop) "Out of Play" else "Available"}: " - val name = askCandidate(prompt, algerianCandidates(_.canTakeBase)) + val name = askSpace(prompt, algerianCandidates(_.canTakeBase)) if (oop) placePiecesFromOutOfPlay(name, Pieces(govBases = 1)) else { @@ -1726,7 +1729,7 @@ object Cards { def replaceBases(remaining: Int): Unit = { val candidates = algerianCandidates(_.flnBases > 0) if (remaining > 0 && candidates.nonEmpty) { - val name = askCandidate("\nSelect Algerian space with an FLN base: ", candidates) + val name = askSpace("\nSelect Algerian space with an FLN base: ", candidates) removeToAvailable(name, Pieces(flnBases = 1)) if (game.guerrillasAvailable > 0) placePieces(name, Pieces(hiddenGuerrillas = 1)) diff --git a/src/main/scala/coltwi/ColonialTwilight.scala b/src/main/scala/coltwi/ColonialTwilight.scala index 56098bc..1e8d8c6 100644 --- a/src/main/scala/coltwi/ColonialTwilight.scala +++ b/src/main/scala/coltwi/ColonialTwilight.scala @@ -509,7 +509,7 @@ object ColonialTwilight { markers: List[String] = Nil) { val nameAndZone = { - val z = if (spaceType == Sector) s" $zone" else "" + val z = if (spaceType == Sector) s" [$zone]" else "" s"$name$z" } @@ -587,6 +587,16 @@ object ColonialTwilight { def moghazniTrainOnly = moghazniTrain && !(normalTrain || recallDeGaulleTrain) } + def displaySpace(spaceName: String): String = { + // Filter out "France Track", etc. + if (game.hasSpace(_.name == spaceName)) + game.getSpace(spaceName).nameAndZone + else + spaceName + } + + def displaySpace(space: Space): String = space.nameAndZone + // Default empty spaces val DefaultBarika = Space(Barika, Sector, "I-1", Mountains, 1) val DefaultBatna = Space(Batna, Sector, "I-2", Mountains, 0) @@ -1102,13 +1112,13 @@ object ColonialTwilight { def activateHiddenGuerrillas(spaceName: String, num: Int): Unit = if (num > 0) { val sp = game.getSpace(spaceName) game = game.updatePieces(sp, sp.activateGuerrillas(num)) - log(s"Flip ${hiddenG(num)} to active in $spaceName") + log(s"Flip ${hiddenG(num)} to active in ${sp.nameAndZone}") } def hideActiveGuerrillas(spaceName: String, num: Int): Unit = if (num > 0) { val sp = game.getSpace(spaceName) game = game.updatePieces(sp, sp.hideGuerrillas(num)) - log(s"Flip ${activeG(num)} to underground in $spaceName") + log(s"Flip ${activeG(num)} to underground in ${sp.nameAndZone}") } def increaseResources(role: Role, amount: Int): Unit = if (amount > 0) { @@ -1159,14 +1169,14 @@ object ColonialTwilight { val sp = game.getSpace(name) assert(game.terrorMarkersAvailable >= num, "addTerror: not enough available markers") game = game.updateSpace(sp.addMarker(TerrorMarker, num)) - log(s"Add ${amountOf(num, "terror marker")} to $name") + log(s"Add ${amountOf(num, "terror marker")} to ${sp.nameAndZone}") } def removeTerror(name: String, num: Int): Unit = if (num > 0) { val sp = game.getSpace(name) assert(sp.terror >= num, "removeTerror: not enought markers in space") game = game.updateSpace(sp.removeMarker(TerrorMarker, num)) - log(s"Remove ${amountOf(num, "terror marker")} from $name") + log(s"Remove ${amountOf(num, "terror marker")} from ${sp.nameAndZone}") } def addResettledMarker(name: String): Unit = { @@ -1240,11 +1250,11 @@ object ColonialTwilight { assert(orig.name == updated.name, "logControlChange: not the same space!") if (orig.control != updated.control) { if (updated.control == Uncontrolled) - log(s"Remove ${orig.control} marker from ${orig.name}") + log(s"Remove ${orig.control} marker from ${orig.nameAndZone}") else if (orig.control == Uncontrolled) - log(s"Place ${updated.control} marker in ${orig.name}") + log(s"Place ${updated.control} marker in ${orig.nameAndZone}") else - log(s"Flip control marker to ${updated.control} in ${orig.name}") + log(s"Flip control marker to ${updated.control} in ${orig.nameAndZone}") } } @@ -1252,11 +1262,11 @@ object ColonialTwilight { assert(orig.name == updated.name, "logSupportChange: not the same space!") if (orig.support != updated.support) { if (updated.support == Neutral) - log(s"Remove ${orig.support} marker from ${orig.name}") + log(s"Remove ${orig.support} marker from ${orig.nameAndZone}") else if (orig.support == Neutral) - log(s"Place ${updated.support} marker in ${orig.name}") + log(s"Place ${updated.support} marker in ${orig.nameAndZone}") else - log(s"Flip support marker to ${updated.support} in ${orig.name}") + log(s"Flip support marker to ${updated.support} in ${orig.nameAndZone}") // Log change in score if (orig.support != Neutral && updated.support != Neutral) { log(s"Move 'Support+Commit' marker to ${game.govScore}") @@ -1471,6 +1481,36 @@ object ColonialTwilight { case xs => askOneOf(prompt, xs, allowNone = true, allowAbort = false) } } + + def askSpace(prompt: String, candidates: List[String], allowAbort: Boolean = true): String = { + val displays = candidates map displaySpace + if (candidates.length > 10) { + val candidateMap = displays.zip(candidates).toMap + val selected = askCandidate(prompt, displays, allowAbort) + candidateMap(selected) + } else { + val choices = candidates.zip(displays) + println() + println(prompt) + askMenu(choices, allowAbort = allowAbort).head + } + } + + def askSpaceAllowNone(prompt: String, candidates: List[String], allowAbort: Boolean = true): Option[String] = { + val displays = candidates map displaySpace + if (candidates.length > 10) { + val candidateMap = displays.zip(candidates).toMap + val selected = askCandidateAllowNone(prompt, displays) + selected map candidateMap.apply + } else { + var choices = candidates.zip(displays).map { + case (candidate, display) => (Some(candidate), display) + } :+ (None, "Cancel space selection") + println() + println(prompt) + askMenu(choices, allowAbort = allowAbort).head + } + } val ALL_WILAYAS = Set("I", "II", "III", "IV", "V", "VI") @@ -1554,7 +1594,7 @@ object ColonialTwilight { Pieces() } else { - println(s"\nPlace up to ${amountOf(maxPieces, "piece")} in $spaceName (${andList(availTypes)})") + println(s"\nPlace up to ${amountOf(maxPieces, "piece")} in ${displaySpace(spaceName)} (${andList(availTypes)})") def nextType(placed: Pieces, remainingTypes: List[PieceType]): Pieces = { val maxRemaining = maxPieces - placed.total @@ -1614,7 +1654,7 @@ object ColonialTwilight { removed ++ (candidates map (n => (n -> game.getSpace(n).numOf(pieceType)))) } else { - val name = askCandidate(s"\nSelect space to remove $pieceType: ", candidates) + val name = askSpace(s"\nSelect space to remove $pieceType: ", candidates) val numInSpace = game.getSpace(name).numOf(pieceType) min numLeft val minFromSpace = 1 max (numLeft - (avail - numInSpace)) val x = if (minFromSpace == numInSpace) numInSpace @@ -1629,7 +1669,7 @@ object ColonialTwilight { for ((name, number) <- removed; sp = game.getSpace(name)) { val updated = sp.copy(pieces = sp.remove(number, pieceType)) game = game.updateSpace(updated) - log(s"Remove ${amtPiece(number, pieceType)} from $name to AVAILABLE") + log(s"Remove ${amtPiece(number, pieceType)} from ${sp.nameAndZone} to AVAILABLE") logControlChange(sp, updated) } } @@ -1642,7 +1682,7 @@ object ColonialTwilight { val sp = game.getSpace(spaceName) val updated = sp.copy(pieces = sp.pieces + pieces) game = game.updateSpace(updated) - log(s"\nPlace the following pieces from AVAILABLE into $spaceName:") + log(s"\nPlace the following pieces from AVAILABLE into ${sp.nameAndZone}:") wrap(" ", pieces.stringItems) foreach (log(_)) if (logControl) logControlChange(sp, updated) @@ -1695,7 +1735,7 @@ object ColonialTwilight { val sp = game.getSpace(spaceName) val updated = sp.copy(pieces = sp.pieces + pieces) game = game.updateSpace(updated).copy(outOfPlay = game.outOfPlay - pieces) - log(s"\nPlace the following pieces from OUT-OF-PLAY into $spaceName:") + log(s"\nPlace the following pieces from OUT-OF-PLAY into ${displaySpace(spaceName)}:") wrap(" ", pieces.stringItems) foreach (log(_)) logControlChange(sp, updated) if (pieces.flnBases > 0) @@ -1704,10 +1744,10 @@ object ColonialTwilight { def removeToAvailable(spaceName: String, pieces: Pieces, logControl: Boolean = true): Unit = if (pieces.total > 0) { val sp = game.getSpace(spaceName) - assert(sp.pieces contains pieces, s"$spaceName does not contain all requested pieces: $pieces") + assert(sp.pieces contains pieces, s"${sp.nameAndZone} does not contain all requested pieces: $pieces") val updated = sp.copy(pieces = sp.pieces - pieces) game = game.updateSpace(updated) - log(s"\nMove the following pieces from $spaceName to AVAILABLE:") + log(s"\nMove the following pieces from ${sp.nameAndZone} to AVAILABLE:") wrap(" ", pieces.stringItems) foreach (log(_)) if (logControl) logControlChange(sp, updated) @@ -1717,7 +1757,7 @@ object ColonialTwilight { def removeToCasualties(spaceName: String, pieces: Pieces, logControl: Boolean = true): Unit = if (pieces.total > 0) { val sp = game.getSpace(spaceName) - assert(sp.pieces contains pieces, s"$spaceName does not contain all requested pieces: $pieces") + assert(sp.pieces contains pieces, s"${sp.nameAndZone} does not contain all requested pieces: $pieces") val updated = sp.copy(pieces = sp.pieces - pieces) // Guerrillas in casualties are always hidden. val toCasualties = if (pieces.activeGuerrillas == 0) @@ -1725,7 +1765,7 @@ object ColonialTwilight { else pieces.remove(pieces.activeGuerrillas, ActiveGuerrillas).add(pieces.activeGuerrillas, HiddenGuerrillas) game = game.updateSpace(updated).copy(casualties = game.casualties + toCasualties) - log(s"\nMove the following pieces from $spaceName to CASUALTIES:") + log(s"\nMove the following pieces from ${sp.nameAndZone} to CASUALTIES:") wrap(" ", pieces.stringItems) foreach (log(_)) if (logControl) logControlChange(sp, updated) @@ -1735,7 +1775,7 @@ object ColonialTwilight { def removeToOutOfPlay(spaceName: String, pieces: Pieces): Unit = if (pieces.total > 0) { val sp = game.getSpace(spaceName) - assert(sp.pieces contains pieces, s"$spaceName does not contain all requested pieces: $pieces") + assert(sp.pieces contains pieces, s"${sp.nameAndZone} does not contain all requested pieces: $pieces") val updated = sp.copy(pieces = sp.pieces - pieces) // Guerrillas in casualties are always hidden. val toOop = if (pieces.activeGuerrillas == 0) @@ -1744,7 +1784,7 @@ object ColonialTwilight { pieces.remove(pieces.activeGuerrillas, ActiveGuerrillas).add(pieces.activeGuerrillas, HiddenGuerrillas) game = game.updateSpace(updated).copy(outOfPlay = game.outOfPlay + toOop) - log(s"\nMove the following pieces from $spaceName to OUT-OF-PLAY:") + log(s"\nMove the following pieces from ${sp.nameAndZone} to OUT-OF-PLAY:") wrap(" ", pieces.stringItems) foreach (log(_)) logControlChange(sp, updated) if (pieces.flnBases > 0) @@ -1762,7 +1802,7 @@ object ColonialTwilight { val updatedSrc = srcSpace.copy(pieces = srcSpace.pieces - pieces) val updatedDst = dstSpace.copy(pieces = dstSpace.pieces + finalPieces) game = game.updateSpace(updatedSrc).updateSpace(updatedDst) - log(s"\nMove the following pieces from $source to $dest:") + log(s"\nMove the following pieces from ${srcSpace.nameAndZone} to ${dstSpace.nameAndZone}:") wrap(" ", pieces.stringItems) foreach (log(_)) if (activateGuerrillas && pieces.hiddenGuerrillas > 0) log(s"Activate the ${hiddenG(pieces.hiddenGuerrillas)}") @@ -1780,7 +1820,7 @@ object ColonialTwilight { val updatedSrc = srcSpace.copy(pieces = srcSpace.pieces - pieces) val updatedDst = dstSpace.copy(pieces = dstSpace.pieces + pieces) game = game.updateSpace(updatedSrc).updateSpace(updatedDst) - log(s"\nRedeploy the following pieces from $source to $dest:") + log(s"\nRedeploy the following pieces from ${srcSpace.nameAndZone} to ${dstSpace.nameAndZone}:") wrap(" ", pieces.stringItems) foreach (log(_)) } @@ -1801,7 +1841,7 @@ object ColonialTwilight { var gToCasualties = totalGuerrillasLost / 2 for ((spaceName, lostPieces) <- losses) { - // log(s"\nLosses for $spaceName:") + // log(s"\nLosses for ${toNameAndZone(spaceName)}:") // wrap(" ", lostPieces.stringItems) foreach (log(_)) val orig = game.getSpace(spaceName) removeToCasualties(spaceName, lostPieces.only(GOV_PIECES), logControl = false) @@ -1859,15 +1899,7 @@ object ColonialTwilight { b += s.toString b.toList } - - def pause(): Unit = { - import scala.util.Properties.isWin - if (isWin) - readLine("Press Enter to continue... ") - else - readLine("Continue ↩︎ ") - } - + var echoLogging = true // Print the line to the console and save it in the game's history. def log(line: String = ""): Unit = { @@ -1876,6 +1908,15 @@ object ColonialTwilight { game = game.copy(history = game.history :+ line) } + def pause(): Unit = { + // Do not pause if we are not printing to the terminal + if (echoLogging) + readLine("\n>>>>> [ Press Enter to continue... ] <<<<<") + else { + println("CWS - pause() called with echoLogging false") + } + } + def separator(length: Int = 52, char: Char = '-'): String = char.toString * length @@ -2772,7 +2813,7 @@ object ColonialTwilight { } def logAdjustment(spaceName: String, attributeName: String, oldValue: Any, newValue: Any): Unit = - logAdjustment(s"$spaceName: $attributeName", oldValue, newValue) + logAdjustment(s"${displaySpace(spaceName)}: $attributeName", oldValue, newValue) def adjustInt(name: String, current: Int, range: Range): Option[Int] = { val prompt = s"$name is $current. Enter new value (${range.min} - ${range.max}) " @@ -3079,7 +3120,7 @@ object ColonialTwilight { case _ => pickFrom.numOf(pieceType) } if (maxNum == 0) { - println(s"There are no ${pieceType} available to add to $name.") + println(s"There are no ${pieceType} available to add to ${sp.nameAndZone}.") pause() } else { diff --git a/src/main/scala/coltwi/Human.scala b/src/main/scala/coltwi/Human.scala index dc38ae0..7912e30 100644 --- a/src/main/scala/coltwi/Human.scala +++ b/src/main/scala/coltwi/Human.scala @@ -97,7 +97,7 @@ object Human { // the space. def checkPeaceOfTheBrave(spaceName: String): Unit = { val sp = game.getSpace(spaceName) - val prompt = s"\nDo you wish pay 1 resource to remove 1 guerrilla from $spaceName (y/n) " + val prompt = s"\nDo you wish pay 1 resource to remove 1 guerrilla from ${displaySpace(spaceName)} (y/n) " if (momentumInPlay(MoPeaceOfTheBrave) && game.resources(Gov) > 0 && sp.totalGuerrillas > 0 && askYorN(prompt)) { decreaseResources(Gov, 1) removeToAvailable(spaceName, askPieces(sp.pieces, 1, GUERRILLAS)) @@ -164,7 +164,7 @@ object Human { println(s"\nChoose one (${amtRes(Gov)} remaining):") askMenu(choices, allowAbort = false).head match { case "space" => - askCandidateAllowNone(s"\nChoose space to Train: ", candidateSpaces.toList.sorted(TrainingSpaceOrdering)) foreach { spaceName => + askSpaceAllowNone(s"\nChoose space to Train: ", candidateSpaces.toList.sorted(TrainingSpaceOrdering)) foreach { spaceName => if (trainInSpace(spaceName, params)) trainSpaces += spaceName } @@ -194,7 +194,7 @@ object Human { val savedState = game try { log() - log(s"$Gov executes Train operation: $spaceName") + log(s"$Gov executes Train operation: ${displaySpace(spaceName)}") if (!params.free) { log() decreaseResources(Gov, 2) @@ -214,7 +214,7 @@ object Human { } catch { case AbortAction => - println(s"\n>>>> Aborting Train operation in $spaceName <<<<") + println(s"\n>>>> Aborting Train operation in ${displaySpace(spaceName)} <<<<") println(separator()) displayGameStateDifferences(game, savedState) game = savedState @@ -232,7 +232,7 @@ object Human { val prompt = if (completed == 0) "\nDo you wish to pacify in one of the training spaces? (y/n) " else "\nDo you wish to pacify in a second training space? (y/n) " if (completed < maxSpaces && candidates.nonEmpty && game.resources(Gov) > 1 && askYorN(prompt)) { - val name = askCandidate("Choose space to pacify: ", candidates.toList.sorted, allowAbort = false) + val name = askSpace("Choose space to pacify: ", candidates.toList.sorted, allowAbort = false) val sp = game.getSpace(name) val maxInSpace = sp.terror + 1 val maxPossible = maxInSpace min (game.resources(Gov) / 2) @@ -255,7 +255,7 @@ object Human { } } - if (candidateSpaces.nonEmpty) { + if (candidateSpaces.nonEmpty && game.resources(Gov) > 1) { println(s"\nYou may pacify in up to ${maxSpaces} of the training spaces") nextPacify(0, candidateSpaces) } @@ -299,23 +299,23 @@ object Human { println(s"\nChoose one: (${amountOf(totalMoved, "Police cube")} moved so far)") askMenu(choices, allowAbort = false).head match { case "space" => - garrisoned += askCandidate(s"Select destination space: ", destCandidates) + garrisoned += askSpace(s"Select destination space: ", destCandidates) nextChoice() case "police" => val savedState = game try { - val source = askCandidate(s"\nSelect space with police cubes: ", sourceCandidates) + val source = askSpace(s"\nSelect space with police cubes: ", sourceCandidates) val dest = if (garrisoned.size == 1) garrisoned.toList.head else - askCandidate(s"Select destination for cubes: ", garrisoned.toList.sorted) + askSpace(s"Select destination for cubes: ", garrisoned.toList.sorted) if (source == dest) println("Nothing to move, since the source and destination are the same.") else { val sp = game.getSpace(source) val most = (6 - totalMoved) min movablePolice(sp).total - val num = askInt(s"Move how many police from $source to $dest", 0, most) + val num = askInt(s"Move how many police from ${displaySpace(sp)} to ${displaySpace(dest)}", 0, most) val p = askPieces(movablePolice(sp), num, POLICE) movePieces(p, source, dest) movingGroups.add(dest, p) @@ -365,7 +365,7 @@ object Human { val candidates = spaceNames(spaces(garrisoned.toList.sorted) filter (guerrillasActivated(_) > 0)) if (candidates.nonEmpty) { val name = if (candidates.size == 1) candidates.head - else askCandidate(s"Choose space to activate guerrillas: ", candidates, allowAbort = false) + else askSpace(s"Choose space to activate guerrillas: ", candidates, allowAbort = false) val sp = game.getSpace(name) activateHiddenGuerrillas(name, guerrillasActivated(sp)) } @@ -430,7 +430,7 @@ object Human { println(s"\nChoose one:") askMenu(choices, allowAbort = false).head match { case "select" => - askCandidateAllowNone(s"\nChoose space to Sweep: ", sweepCandidates.toList.sorted) foreach { spaceName => + askSpaceAllowNone(s"\nChoose space to Sweep: ", sweepCandidates.toList.sorted) foreach { spaceName => if (sweepInSpace(spaceName, params)) sweepSpaces += spaceName } @@ -439,7 +439,7 @@ object Human { nextChoice() case "activate" => - askCandidateAllowNone(s"\nChoose space to activate guerrillas: ", activateSpaces.sorted) foreach { spaceName => + askSpaceAllowNone(s"\nChoose space to activate guerrillas: ", activateSpaces.sorted) foreach { spaceName => activateHiddenGuerrillas(spaceName, guerrillasActivated(game.getSpace(spaceName))) activatedSpaces += spaceName } @@ -478,7 +478,7 @@ object Human { val savedState = game try { log() - log(s"$Gov executes Sweep operation: $spaceName") + log(s"$Gov executes Sweep operation: ${displaySpace(spaceName)}") if (!params.free) { log() decreaseResources(Gov, 2) @@ -488,9 +488,9 @@ object Human { def nextSource(): Unit = { val sources = sourceSpaces(game.getSpace(spaceName)) if (sources.nonEmpty) { - val choices = (sources map (name => name -> s"Move troops from $name")) :+ - "done" -> s"Finished moving troops to $spaceName from adjacent spaces" :+ - "abort" -> s"Abort the sweep operation in $spaceName" + val choices = (sources map (name => name -> s"Move troops from ${displaySpace(name)}")) :+ + "done" -> s"Finished moving troops to ${displaySpace(spaceName)} from adjacent spaces" :+ + "abort" -> s"Abort the sweep operation in ${displaySpace(spaceName)}" println(s"\nChoose one:") askMenu(choices, allowAbort = false).head match { case "done" => @@ -518,7 +518,7 @@ object Human { } catch { case AbortAction => - println(s"\n>>>> Aborting Sweep operation in $spaceName <<<<") + println(s"\n>>>> Aborting Sweep operation in ${displaySpace(spaceName)} <<<<") println(separator()) displayGameStateDifferences(game, savedState) game = savedState @@ -575,9 +575,9 @@ object Human { println(s"\nChoose one:") askMenu(choices, allowAbort = false).head match { case "assault" => - askCandidateAllowNone(s"\nChoose space to Assault: ", assaultCandidates.toList.sorted) foreach { spaceName => + askSpaceAllowNone(s"\nChoose space to Assault: ", assaultCandidates.toList.sorted) foreach { spaceName => log() - log(s"$Gov executes Assault operation: $spaceName") + log(s"$Gov executes Assault operation: ${displaySpace(spaceName)}") if (!params.free) decreaseResources(Gov, costPerSpace) checkPeaceOfTheBrave(spaceName) @@ -701,7 +701,7 @@ object Human { val spaceChoice = if (deploySpaces.size < 4) List("space" -> "Select a map space for deployment") else Nil val deployChoices = if (deploySpaces.size > 1 && numMoved < 6) for (name <- deploySpaceNames; if movable(name).total > 0) - yield (name -> s"Deploy pieces out of $name (${movable(name)})") + yield (name -> s"Deploy pieces out of ${displaySpace(name)} (${movable(name)})") else Nil @@ -713,7 +713,7 @@ object Human { println(s"${amountOf(numMoved, "piece")} moved so far") askMenu(choices).head match { case "space" => - val name = askCandidate("Select deployment space: ", getMoveCandidates) + val name = askSpace("Select deployment space: ", getMoveCandidates) deploySpaces += name -> Pieces() nextAction() case "done" => @@ -724,9 +724,9 @@ object Human { nextAction() case src => val candidates = deploySpaceNames filterNot (_ == src) - val dest = if (candidates.size == 1) candidates.head else askCandidate("Select destination: ", candidates) + val dest = if (candidates.size == 1) candidates.head else askSpace("Select destination: ", candidates) val srcPieces = movable(src) - val num = askInt(s"Deploy how many pieces from $src to $dest", 0, srcPieces.total min (6 - numMoved)) + val num = askInt(s"Deploy how many pieces from ${displaySpace(src)} to ${displaySpace(dest)}", 0, srcPieces.total min (6 - numMoved)) if (num > 0) { val pieces = askPieces(srcPieces, num) (src, dest) match { @@ -745,7 +745,7 @@ object Human { // Resettle - Choose one space and place a resettled marker there // Remove any support/opposition def resettleSpace(params: Params): Unit = { - addResettledMarker(askCandidate("Resettle which space? ", getResettleCandidates.toList.sorted)) + addResettledMarker(askSpace("Resettle which space? ", getResettleCandidates.toList.sorted)) } } @@ -771,7 +771,7 @@ object Human { val spaceChoice = if (selectedSpaces.size < maxSpaces) List("space" -> "Select a Troop Lift space") else Nil val liftChoices = if (selectedSpaces.size > 1) (selectedSpaces.sorted filter (name => game.getSpace(name).frenchTroops > 0) - map (name => name -> s"Lift French troops out of $name")) + map (name => name -> s"Lift French troops out of ${displaySpace(name)}")) else Nil val choices = spaceChoice ::: liftChoices ::: List( @@ -788,13 +788,13 @@ object Human { else liftTroops(selectedSpaces) case "space" => val candidates = spaceNames(game.algerianSpaces) filterNot selectedSpaces.contains - val name = askCandidate("Select Troop Lift space: ", candidates.sorted) + val name = askSpace("Select Troop Lift space: ", candidates.sorted) liftTroops(name :: selectedSpaces) case src => - val dest = askCandidate("\nSelect destination for French troops: ", selectedSpaces.sorted filterNot (_ == src)) + val dest = askSpace("\nSelect destination for French troops: ", selectedSpaces.sorted filterNot (_ == src)) val srcSpace = game.getSpace(src) - askInt(s"Lift how many French troops from $src to $dest", 0, srcSpace.frenchTroops) match { + askInt(s"Lift how many French troops from ${srcSpace.nameAndZone} to ${displaySpace(dest)}", 0, srcSpace.frenchTroops) match { case 0 => case num => val (pieces, swept) = askFrenchTroops(srcSpace, movingGroups(src), num) @@ -868,7 +868,7 @@ object Human { println("Choose one:") askMenu(choices).head match { case "select" => - val name = askCandidate("Select space: ", candidates.toList.sorted) + val name = askSpace("Select space: ", candidates.toList.sorted) selectSpaces(name :: selected) case "done" => selected case "abort" => if (askYorN("Really abort? (y/n) ")) throw AbortAction else selectSpaces(selected) @@ -942,8 +942,8 @@ object Human { println() if (torture.total > 0) - println(s"$torture will be removed from $name due to the Torture capability") - println(s"Choose pieces to remove from $name:") + println(s"$torture will be removed from ${displaySpace(name)} due to the Torture capability") + println(s"Choose pieces to remove from ${displaySpace(name)}:") askMenu(choices).head } (name -> (removed + torture)) :: nextSpace(remainingSpaces.tail, numRemoved + removed.total) @@ -951,7 +951,8 @@ object Human { val losses = nextSpace(selectSpaces(Nil).reverse, 0) val spaceNames = losses map (_._1) - log(s"\nGovernment neutralizes in ${andList(spaceNames)}") + val displayNames = spaceNames map displaySpace + log(s"\nGovernment neutralizes in ${andList(displayNames)}") removeLosses(losses) log() for (name <- spaceNames; sp = game.getSpace(name)) { @@ -1066,7 +1067,7 @@ object Human { val candidates = spaceNames(game.algerianSpaces filter (sp => !pacified(sp.name) && canPacify(sp))).sorted val maxResources = game.resources(Gov) min (game.commitment - totalSpent) if (candidates.nonEmpty && maxResources > 1) { - val choices = (candidates map (name => name -> s"Pacify in $name")) :+ ("done" -> "Finished pacifying") + val choices = (candidates map (name => name -> s"Pacify in ${displaySpace(name)}")) :+ ("done" -> "Finished pacifying") println() println(s"\nResources available: ${game.resources(Gov)}, Resources spent: $totalSpent, Gov commitment: ${game.commitment}") println("Choose one:") @@ -1092,7 +1093,7 @@ object Human { nextPacify(pacified, totalSpent) else { val spentThisSpace = num * 2; - log(s"\nGovernment pacifies: $name") + log(s"\nGovernment pacifies: ${sp.nameAndZone}") log(separator()) decreaseResources(Gov, spentThisSpace) removeTerror(name, num min sp.terror) @@ -1120,10 +1121,10 @@ object Human { case "done" => case "redeploy" => try { - val srcName = askCandidate("\nSelect space with troops: ", sources, allowAbort = false) - val destName = askCandidate("Select destination space: ", dests filterNot (_ == srcName), allowAbort = false) + val srcName = askSpace("\nSelect space with troops: ", sources, allowAbort = false) + val destName = askSpace("Select destination space: ", dests filterNot (_ == srcName), allowAbort = false) val src = game.getSpace(srcName) - val num = askInt(s"Deploy how many troops out of $srcName", 0, src.totalTroops, allowAbort = false) + val num = askInt(s"Deploy how many troops out of ${src.nameAndZone}", 0, src.totalTroops, allowAbort = false) val troops = askPieces(src.pieces, num, TROOPS, allowAbort = false) redeployed = true redeployPieces(troops, srcName, destName) @@ -1150,10 +1151,10 @@ object Human { case "done" => case "redeploy" => try { - val srcName = askCandidate("\nSelect space with police: ", sources, allowAbort = false) - val destName = askCandidate("Select destination space: ", dests filterNot (_ == srcName), allowAbort = false) + val srcName = askSpace("\nSelect space with police: ", sources, allowAbort = false) + val destName = askSpace("Select destination space: ", dests filterNot (_ == srcName), allowAbort = false) val src = game.getSpace(srcName) - val num = askInt(s"Deploy how many police out of $srcName", 0, src.totalPolice, allowAbort = false) + val num = askInt(s"Deploy how many police out of ${src.nameAndZone}", 0, src.totalPolice, allowAbort = false) val police = askPieces(src.pieces, num, POLICE, allowAbort = false) redeployed = true redeployPieces(police, srcName, destName)