|
|
|
|
@ -18,6 +18,9 @@ interface ActionManager { |
|
|
|
|
fun blindsUpdated(type: Action.Type, amount: Double) |
|
|
|
|
fun minimumBetAmount(index: Int): Double |
|
|
|
|
fun totalPotSize(index: Int): Double |
|
|
|
|
fun initialStack(position: Int): Double? |
|
|
|
|
fun stackForNewAction(action: Action): Double? |
|
|
|
|
fun stackAtStreetStart(index: Int): Double? |
|
|
|
|
val heroIndex: Int? |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -60,7 +63,6 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
this, |
|
|
|
|
action, |
|
|
|
|
totalPotSize, |
|
|
|
|
action.positionRemainingStack, |
|
|
|
|
position |
|
|
|
|
) |
|
|
|
|
computedActions.add(ca) |
|
|
|
|
@ -88,15 +90,31 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
*/ |
|
|
|
|
override fun selectAction(index: Int, actionType: Action.Type) { |
|
|
|
|
|
|
|
|
|
var type = actionType |
|
|
|
|
val computedAction = this[index] |
|
|
|
|
|
|
|
|
|
// Automatically sets action for the previous empty actions |
|
|
|
|
val modifiedActions = mutableListOf<ComputedAction>() |
|
|
|
|
getPreviousEmptyActions(index).forEach { |
|
|
|
|
modifiedActions.add(it) |
|
|
|
|
val lastSignificant = getStreetLastSignificantAction(computedAction.street, index - 1) |
|
|
|
|
it.action.type = if (lastSignificant != null) { |
|
|
|
|
Action.Type.FOLD |
|
|
|
|
} else { |
|
|
|
|
Action.Type.CHECK |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var type = actionType |
|
|
|
|
|
|
|
|
|
// define allin type |
|
|
|
|
if (type == Action.Type.UNDEFINED_ALLIN) { |
|
|
|
|
|
|
|
|
|
when (type) { |
|
|
|
|
Action.Type.UNDEFINED_ALLIN -> { |
|
|
|
|
|
|
|
|
|
val significant = getStreetLastSignificantAction(computedAction.street, index - 1) |
|
|
|
|
type = if (significant != null) { |
|
|
|
|
val betAmount = significant.action.amount |
|
|
|
|
val remainingStack = computedAction.playerRemainingStack |
|
|
|
|
val remainingStack = computedAction.stackBeforeActing |
|
|
|
|
if (remainingStack != null && betAmount != null && remainingStack < betAmount) { |
|
|
|
|
Action.Type.CALL_ALLIN |
|
|
|
|
} else { |
|
|
|
|
@ -105,25 +123,24 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
} else { |
|
|
|
|
Action.Type.BET_ALLIN |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Timber.d(">>> Sets $type at index: $index") |
|
|
|
|
|
|
|
|
|
computedAction.setType(type) // false |
|
|
|
|
|
|
|
|
|
// Automatically sets action for the previous empty actions |
|
|
|
|
val modifiedActions = mutableListOf<ComputedAction>() |
|
|
|
|
getPreviousEmptyActions(index).forEach { |
|
|
|
|
modifiedActions.add(it) |
|
|
|
|
val lastSignificant = getStreetLastSignificantAction(computedAction.street, index - 1) |
|
|
|
|
it.action.type = if (lastSignificant != null) { |
|
|
|
|
Action.Type.FOLD |
|
|
|
|
} else { |
|
|
|
|
Action.Type.CHECK |
|
|
|
|
} |
|
|
|
|
Action.Type.CALL -> { |
|
|
|
|
getStreetLastSignificantAction(computedAction.street, index - 1)?.action?.amount?.let { betAmount -> |
|
|
|
|
val remainingStack = computedAction.stackBeforeActing |
|
|
|
|
if (remainingStack != null && remainingStack < betAmount) { |
|
|
|
|
type = Action.Type.CALL_ALLIN |
|
|
|
|
} |
|
|
|
|
} ?: throw PAIllegalStateException("Can't happen") |
|
|
|
|
} |
|
|
|
|
else -> {} |
|
|
|
|
} |
|
|
|
|
Timber.d(">>> Sets $type at index: $index") |
|
|
|
|
|
|
|
|
|
computedAction.setType(type) |
|
|
|
|
|
|
|
|
|
this.updateFollowupActions(index) |
|
|
|
|
this.updateRemainingStacksForPositions(listOf(computedAction.action.position)) |
|
|
|
|
|
|
|
|
|
fireListener() |
|
|
|
|
} |
|
|
|
|
@ -133,7 +150,8 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
*/ |
|
|
|
|
fun setAmount(index: Int, amount: Double) { |
|
|
|
|
val computedAction = this[index] |
|
|
|
|
computedAction.setAmount(amount) |
|
|
|
|
computedAction.setBetAmount(amount) |
|
|
|
|
this.updateRemainingStacksForPositions(listOf(computedAction.action.position)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
@ -180,7 +198,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
return if (lastSignificantAction == null) { |
|
|
|
|
setOf(Action.Type.FOLD, Action.Type.CHECK, Action.Type.BET, Action.Type.POT, Action.Type.UNDEFINED_ALLIN) |
|
|
|
|
} else { |
|
|
|
|
val remainingStack = getLastPlayerAction(index)?.playerRemainingStack |
|
|
|
|
val remainingStack = computedAction.stackBeforeActing |
|
|
|
|
val actionAmount = lastSignificantAction.action.amount |
|
|
|
|
|
|
|
|
|
when (lastSignificantAction.action.type) { |
|
|
|
|
@ -273,15 +291,6 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
return this.take(index).filter { it.street == street && it.action.type == null } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Returns the last user action, if any, for the action at the provided [index] |
|
|
|
|
*/ |
|
|
|
|
private fun getLastPlayerAction(index: Int): ComputedAction? { |
|
|
|
|
val action = this[index].action |
|
|
|
|
val previousActions = this.take(index) |
|
|
|
|
return previousActions.lastOrNull { it.positionIndex == action.position } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Returns the last significant player action, if any, for the action at the provided [index] |
|
|
|
|
*/ |
|
|
|
|
@ -319,7 +328,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
activePositions.indexOfFirst { it.ordinal > refIndexPosition.ordinal }) |
|
|
|
|
for (i in 0 until activePositions.size) { |
|
|
|
|
val position = activePositions[(firstPositionAfterCurrent + i) % activePositions.size] |
|
|
|
|
this.addNewEmptyAction(position, refAction.street, refAction.totalPotSize, lastRemainingStack(position, index)) |
|
|
|
|
this.addNewEmptyAction(position, refAction.street, refAction.totalPotSize) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (activePositions.isNotEmpty()) { |
|
|
|
|
@ -330,7 +339,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
/*** |
|
|
|
|
* Creates a new action at the end of the action stack, and in the HH representation |
|
|
|
|
*/ |
|
|
|
|
private fun addNewEmptyAction(position: Position, street: Street, currentPotSize: Double, remainingStack: Double?) { |
|
|
|
|
private fun addNewEmptyAction(position: Position, street: Street, currentPotSize: Double) { |
|
|
|
|
|
|
|
|
|
if (street == Street.SUMMARY) { |
|
|
|
|
throw PAIllegalStateException("Summary cannot have player actions") |
|
|
|
|
@ -345,7 +354,6 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
this, |
|
|
|
|
action, |
|
|
|
|
currentPotSize, |
|
|
|
|
remainingStack, |
|
|
|
|
position |
|
|
|
|
) |
|
|
|
|
this.add(computedAction) |
|
|
|
|
@ -353,13 +361,6 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
this.sizeChanged = true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Returns the last remaining stack of the player, if available |
|
|
|
|
*/ |
|
|
|
|
private fun lastRemainingStack(position: Position, index: Int): Double? { |
|
|
|
|
return this.take(index).lastOrNull { it.position == position }?.playerRemainingStack |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Adds, if necessary, new ComputedAction for players that needs to act |
|
|
|
|
* Also adds, if necessary, the Street separators and board selectors |
|
|
|
|
@ -481,7 +482,8 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
created = true |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
playerSetup.stack = this.filter { it.positionIndex == positionIndex }.sumByDouble { it.action.effectiveAmount } |
|
|
|
|
val stack = this.filter { it.positionIndex == positionIndex }.sumByDouble { it.action.effectiveAmount } |
|
|
|
|
playerSetup.stack = stack |
|
|
|
|
|
|
|
|
|
if (created) { |
|
|
|
|
this.listener.playerSetupCreated() |
|
|
|
|
@ -497,7 +499,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
Action.Type.POST_BB -> { |
|
|
|
|
this.handHistory.bigBlind = amount |
|
|
|
|
if (this.handHistory.bigBlindAnte) { |
|
|
|
|
this.updateRemainingStacksForPositions(listOf()) |
|
|
|
|
this.updateBigBlindRemainingStack() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else -> throw PAIllegalStateException("Should never happen") |
|
|
|
|
@ -586,7 +588,7 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
val lastActionIndex = lastComputedAction.action.index |
|
|
|
|
val isShowDown = street == Street.SUMMARY |
|
|
|
|
activePositions(lastActionIndex, isShowDown).sortedBy { it.ordinal }.forEach { |
|
|
|
|
addNewEmptyAction(it, street, totalPotSize, lastRemainingStack(it, lastActionIndex)) |
|
|
|
|
addNewEmptyAction(it, street, totalPotSize) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -608,23 +610,26 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Recomputes all remaining stacks for the given [positionIndexes] |
|
|
|
|
* Recomputes all remaining stacks for the given [positionIndexes], after the given [index] |
|
|
|
|
*/ |
|
|
|
|
fun updateRemainingStacksForPositions(positionIndexes: List<Int>) { |
|
|
|
|
|
|
|
|
|
val ante = if (this.handHistory.bigBlindAnte) this.handHistory.bigBlind ?: 0.0 else this.handHistory.ante |
|
|
|
|
|
|
|
|
|
positionIndexes.forEach { posIndex -> |
|
|
|
|
val ante = this.handHistory.anteForPosition(this.positions.elementAt(posIndex)) |
|
|
|
|
|
|
|
|
|
this.handHistory.playerSetupForPosition(posIndex)?.stack?.let { initialStack -> |
|
|
|
|
|
|
|
|
|
var remainingStack = initialStack - ante |
|
|
|
|
val startStack = initialStack - ante |
|
|
|
|
val playerActions = this.filter { it.positionIndex == posIndex } |
|
|
|
|
|
|
|
|
|
var previousAction: ComputedAction? = null |
|
|
|
|
playerActions.forEach { |
|
|
|
|
remainingStack -= it.action.effectiveAmount |
|
|
|
|
it.playerRemainingStack = remainingStack |
|
|
|
|
// remainingStack -= it.action.effectiveAmount |
|
|
|
|
it.stackBeforeActing = previousAction?.stackAfterActing ?: startStack |
|
|
|
|
if (it.action.type?.isAllin == true) { |
|
|
|
|
it.action.amount = remainingStack |
|
|
|
|
it.action.amount = this.stackAtStreetStart(it.action.index) |
|
|
|
|
} |
|
|
|
|
previousAction = it |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -632,30 +637,22 @@ class ActionList(var listener: ActionListListener) : ArrayList<ComputedAction>() |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*** |
|
|
|
|
* Updates all ComputedAction linked to the position with an updated value of the remaining stack |
|
|
|
|
*/ |
|
|
|
|
fun stackUpdatedAtPosition(positionIndex: Int) { |
|
|
|
|
this.handHistory.playerSetupForPosition(positionIndex)?.let { playerSetup -> |
|
|
|
|
|
|
|
|
|
var remainingStack = playerSetup.stack |
|
|
|
|
this.filter { it.action.position == positionIndex }.forEach { ca -> |
|
|
|
|
|
|
|
|
|
remainingStack?.let { rs -> |
|
|
|
|
|
|
|
|
|
if (ca.action.type?.isAllin == true) { // updates the action amount |
|
|
|
|
ca.setType(ca.action.type!!) |
|
|
|
|
} else { // updates the remaining stack |
|
|
|
|
remainingStack = rs - ca.action.effectiveAmount |
|
|
|
|
ca.playerRemainingStack = remainingStack |
|
|
|
|
override fun initialStack(position: Int): Double? { |
|
|
|
|
val ante = this.handHistory.anteForPosition(this.positions.elementAt(position)) |
|
|
|
|
return this.handHistory.playerSetupForPosition(position)?.stack?.let { it - ante } ?: run { null} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} ?: run { |
|
|
|
|
ca.playerRemainingStack = null |
|
|
|
|
override fun stackForNewAction(action: Action): Double? { |
|
|
|
|
return this.lastOrNull { it.action.position == action.position }?.stackAfterActing |
|
|
|
|
?: run { |
|
|
|
|
this.initialStack(action.position) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} ?: throw PAIllegalStateException("Can't happen") |
|
|
|
|
override fun stackAtStreetStart(index: Int): Double? { |
|
|
|
|
val computedAction = this[index] |
|
|
|
|
val firstStreetAction = this.firstOrNull { it.street == computedAction.street && it.action.position == computedAction.action.position } |
|
|
|
|
return firstStreetAction?.stackBeforeActing |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|