Dice

Dice is an abstraction for dice in the game. It has two subclasses ActualDice and AbstractDice.

  • ActualDice represents the dice that can be held by a player.

  • AbstractDice represents the dice-cost of different actions.

Dice Class

from dgisim import Dice
class Dice(dice: dict[dgisim.element.Element, int])

Base class for dice

If you want to customize your legal elements, override this attribute in your subclass of Dice.

__init__(dice: dict[dgisim.element.Element, int]) None
Parameters:

dice – the initial dice of this object.

Once dice is passed in, it’ll be stored in an internal frozen dictionary, ensuring immutability.

For performance, you may want to directly pass in a HashableDict object instead of an ordinary dict.

elems() Iterable[Element]
Returns:

all elements that have a number.

get_dices() HashableDict[Element, int]
Returns:

the internal frozen dictionary of dice.

is_empty() bool
Returns:

if total number of dice is even.

Worst time complexity = O(k), k is kinds of dice held by this object.

is_even() bool
Returns:

if total number of dice is even.

Time complexity = O(k), k is kinds of dice held by this object.

Returns:

True if number of each kind of die is non-negative and all are one of the legal elements of this class.

Worst time complexity = O(k), k is kinds of dice held by this object.

num_dice() int
Returns:

total number of dice.

Time complexity = O(k), k is kinds of dice held by this object.

pick_random_dice(num: int) tuple[typing_extensions.Self, typing_extensions.Self]
Parameters:

num – the number of random dice to pick.

Returns:

a tuple of left dice and picked dice.

to_dict() dict[dgisim.element.Element, int]
Returns:

a dicrionary that contains the dice info.

validify() Self
Returns:

validified version of this object. All dice of illegal elements are removed. All kinds of dice with non-positive number are removed.

In additional to the methods listed above, Dice overrides some magic methods for better experience.

from dgisim import Dice, Element

# Note that Element.PIERCING is illegal in Dice
dice1 = Dice({Element.PYRO: 3, Element.ANY: 2, Element.OMNI: 0, Element.PIERCING: 5})
dice2 = Dice({Element.PYRO: 1, Element.GEO: 2})

# in (__contains__)
print(Element.ANY in dice1)       # True
print(Element.OMNI in dice1)      # False, because there's <= 0 OMNI in dice1
print(Element.PIERCING in dice1)  # False, because PIERCING is illegal in dice1

# in (__iter__)
for elem in dice1:
    # only elements with a positive number are iterated
    print(elem)  # Element

# [] (__getitem__)
print(dice1[Element.OMNI])      # 0
print(dice1[Element.PIERCING])  # 5
print(dice1[Element.HYDRO])     # 0

# +, - (__add__, __sub__)
print(dice1 + dice2) # {PYRO: 4, ANY: 2, OMNI: 0, PIERCING: 5, GEO: 2}
print(dice1 - dice2) # {PYRO: 2, ANY: 2, OMNI: 0, PIERCING: 5, GEO: -2}
print(dice1 - {Element.PYRO: 3, Element.OMNI: 1})  # {PYRO: 1, ANY: 2, OMNI: -1, PIERCING: 5}

ActualDice Class

from dgisim import ActualDice
class ActualDice(dice: dict[dgisim.element.Element, int])

Bases: Dice

Used for the actual dice a player can have.

basically_satisfy(requirement: AbstractDice, game_state: None | GameState = None) None | ActualDice
Parameters:

game_state – the context the selection is based on, but not used by this method, so leave it as None by default.

Returns:

a way to fulfill the requirement, not necessarily the smartest solution is returned. If it is impossible to fulfill, then None is returned.

dice_ordered(player_state: None | PlayerState) dict[Element, int]
Returns:

an ordered dictionary of dice contained by self. The ordering follows the in-game top-down ordering when a player has multiple dice.

The return value can be utilized by cards like Liben, Vanarana…

classmethod from_dice(dice: Dice) None | ActualDice
Returns:

a new object of ActualDice if the dice provided is legal in the context of ActualDice.

classmethod from_random(size: int, excepted_elems: set[dgisim.element.Element] = {}) ActualDice
Returns:

a random ActualDice object with size of dice chosen from expected_elems.

just_satisfy(requirement: AbstractDice) bool
Returns:

True if self exactly satisfies requirement, that is not a single extra die is contained.

Asserts self and requirement are legal.

loosely_satisfy(requirement: AbstractDice) bool
Returns:

True if requirement can be satisfied.

Asserts self and requirement are legal.

readonly_dice_ordered(player_state: None | PlayerState) HashableDict[Element, int]
Returns:

the same value as .dice_ordered() but a readonly version.

This method has a better performance.

AbstractDice Class

from dgisim import AbstractDice
class AbstractDice(dice: dict[dgisim.element.Element, int])

Bases: Dice

Used for the dice cost of cards and other actions

can_cost_less_any() bool
Returns:

True if less Element.ANY can be required.

can_cost_less_elem(elem: None | Element = None) bool
Parameters:

elem – if this value is None (by default), then any element is considered, otherwise, only elem is considered.

Returns:

True if less elemental dice can be costed.

cost_less_any(num: int) Self
Returns:

a new AbstractDice object where num less ANY dice are costed.

This method ensures the return value is legal.

cost_less_elem(num: int, elem: None | Element = None) Self
Parameters:

elem – if this value is None (by default), then elements of a particular order are removed (max to num). Otherwise, only dice of elem are removed.

Returns:

a new AbstractDice object where num less elem are required.

classmethod from_dice(dice: Dice) None | AbstractDice
Returns:

a new object of ActualDice if the dice provided is legal in the context of ActualDice.