Fluxx

Introduction:

Fluxx is a mildly popular card game. All things considered, it’s actually fairly contentious. It has a score of 5.7 on Board Game Geek, but it has a serious cult following. This is a python implementation of version 5.0 of the Vanilla Fluxx card game. The full rules are available here. The core idea is that the players can play cards which change the rules of the game. Each turn, each player draws a certain number of cards and plays a certain number of cards. There are four types of cards. There are Keepers, which are laid on the table in front of the player, Goals which determine how the game is won, New Rules which change the rules of the game, and finally Actions, which are played to the discard pile and perform the action printed on the card.

This particular implementation of the game was built from the ground-up, using no third-party libraries or assets. Card text has been abridged slightly, but retains all of the original’s gameplay meaning.

Fluxx is a registered trademark of Looney Labs – College Park, MD 20741-0763

The goal of this project is to create a playground for advanced AI experiments with a complicated, not-analytically-solvable traditional game. Looney Labs has developed a polished and well-made digital version of Fluxx available here. Which is actually optimized for play by humans, and I suggest that anyone who found this project with the intention of playing the game for fun pay them the $0.99 and get the digital edition. That being said, there is a human-interface portion to this project which can be played by running engine.py.

Installation and Use:

To play the game, all you need to do is run engine.py. The construction is fully portable and relies on no third party packages.

For actually interesting uses of this project, a user needs to do the following.

  1. from fluxx.objects import Board
  2. Create an instance of Board, which I will call board.
  3. Use board.info to get a dictionary which contains all of the player-knowable information about the game.
  4. board.info['options'] will show a list of the choices that the player has at the given stage of the game.
  5. Run board.action(option) where option is the index of the desired option in board.info['options'].
  6. Repeat 4 and 5 until a winner becomes apparent. The board.action() will throw a Board.Win exception which contains the number of the player who won.

Objects

Author: Coen D. Needell Copyright: Looney Labs

This file contains all of the ‘meat and potatoes’ of the game. It contains all the objects that the game engine interacts with and does all of the computational work of the game. It’s a card game though, so that’s not too hard. The main purpose is for a Board object to act as a finite state machine which can be controlled using board.action().

class objects.Board(num_players: int)

The Board object houses all of the information about the current game. Each card in the game has to be connected to a Board object.

exception IllegalMove(board, *args)

Thrown when the player tries to do something illegal.

exception IllegalPlay(board, *args)

Thrown when the player tries to play a card in an illegal way. Undoes the card_played effect.

exception Win(*args)

Thrown when the game is won.

action(option)

The method which advances the game.

Parameters:option – int The index of the option (from board.options) which the player would like to perform.
Returns:NoneType
active_player

The player who currently must make a decision. When a limit is resolving, this is the player who must choose what to discard. Otherwise it’s the player whose turn it is.

Returns:int
card_set

Gives a list of all the cards in the game.

Returns:list
cards_seen

Gives a list of all the cards that the active player can see.

Returns:list
check_goal()

Checks to see if the goal has been satisfied. If it has, then it throws a win.

Returns:NoneType
check_rules()

Goes through the list of rules and runs their .rule() methods.

Returns:NoneType
check_starts()

There’s a special class of rules whose rule is only executed at the start of a turn. This runs their .start() method. Those rules’ .rule() methods just run pass.

Returns:NoneType
curr_hand

Gives the active player’s hand.

Returns:Hand
curr_keep

Gives the active player’s keep.

Returns:Keep
draw_state

The total draw rule.

Returns:int
inc_cards_played()

Increases the count of cards played. If the count goes over the play_state, then the turn_state will roll-over to the next player.

Returns:NoneType
inc_player_state()

Increases the turn_num, and calculates the current player state.

Returns:NoneType
info

Gives a dictionary telling the player what they need to know.

Draws:How many draws are allowed.
Plays:How many plays are allowed.
Player:The active player.
Keeps:A list of the Keeps in the game.
Goals:The GoalSpace for the game.
Rules:The RuleSpace for the game.
Discard:The discard pile.
Hand:The active player’s hand.
Options:A list of the things that the active player is allowed to do.
Actiontype:The current type of action that the active player must perform.
Mystery:A description of the most recent MysteryPlay, if there was one.
Remaining:The number of plays the active player has remaining.
Drawn:The number of cards that hte active player has drawn.
Returns:dict
options

Gives a list of the actions that the active player can take. Depends greatly on the current action_type

Returns:list
play_state

The total play rule.

Returns:int
class objects.CardSpace(kind, board)

The generic form of the RuleSpace, GoalSpace, and Keep.

May only hold `Card`s and acts like a MutableSet but with an attached Board.

add(x: objects.Card) → None

Add an element.

discard(x: objects.Card) → None

Remove an element. Do not raise an exception if absent.

class objects.Deck(board)
classmethod discard_creator(board)

Alternate constructor, generates an empty Deck.

Parameters:board – Board
Returns:Deck
draw()

Takes the top Card off of the deck and returns it.

Returns:Card
insert(index: int, value)

S.insert(index, value) – insert value before index

class objects.GoalSpace(board)
add(x)

Runs some special code to ensure that the thing you’re adding is a Goal card. Also makes sure that there is only one (or two with Double Agenda) Goal in play. If Double Agenda is in play, then this initiates a special turn to remove one of those Goals.

Parameters:x – Card
Returns:NoneType
discard(x: objects.Card)

Remove an element. Do not raise an exception if absent.

remove(x)

Remove an element. If not a member, raise a KeyError.

class objects.Hand(player_num, board, _draw=True)
add(x: objects.Card) → None

Add an element.

discard(x: objects.Card) → None

Remove an element. Do not raise an exception if absent.

draw(amount)

Draws amount Card`s from `board.deck.

Parameters:amount – int
Returns:NoneType
classmethod temphand(size, board)

Alternate constructor. Sets _draw=False so that the Hand which is returned is of size size. Draws size cards and is connected to board.

Parameters:
  • size – int
  • board – Board
Returns:

Hand

class objects.Keep(player_num, board)
class objects.RuleSpace(board)
ruleset

Provides a list of the .rule() methods for the rules in the RuleSpace. :return: list[function]

Engine

Author: Coen D. Needell

Copyright: Looney Labs

Fluxx is a registered trademark of Looney Labs – College Park, MD 20741-0763

This file constitutes the ‘Engine’ of the game. In strict terms, the engine is actually split between the object.Board and here, but I’ve called this file engine.py for simplicity. This file contains the interface for the game. After trying a number of interfaces for python scripts, I chose to implement our engine with the standard python input-response loop. The point-of-interface between the engine and the game objects is intended to be minimal. This is because I intend the game to be machine-playable in the case of future development.

engine.card_text_info(card_name)

Returns the card text of the card specified by card_name.

engine.get_card_text()

Runs the ‘read card text’ environment.

engine.interact(entry)

This is the function that interacts with the board.action() method from objects.py.

engine.play_game()

The core environment for the game.

engine.print_info()

Gives the active player information about the game state.

engine.start_screen()

Shows the start screen, and sets up the game.

Assets

The point of defining the Assets folder as seperate from the objects folder is to make it easy to add new assets to the game, especially those which have their own behavior. You’ll notice I didn’t include CREEPERs in the game, because they are considered an auxiliary mechanic by most players. Every card-code in this file which has an underscore before it refers to a card which has special behavior within its class. This behavior is recorded in subclasses for their type. The foodlist is stored here, too.

Indices and tables

This project is dedicated to Daniel Pollak