I enjoy story-telling games. I have various story telling games such as Gloom, a game I made up loosely based on Nanofictionary, The Extraordinary Adventures of Baron Munchausen, and various heavily modified versions of Atlas Games’ Once Upon a Time. Of course the natural thing to do was to come up with my own game. This has a working title of “Story Soup” and about 600 cards … which means to shuffle the cards effectively you need pretty big hands. I have yet to finalise this, but in the meantime I was keen to use it to generate some plots for some stories.
Seeing as I had the card contents on a bunch of files, writing a python script to deal a hand was straight forward. One thing lead to another and I realised the I could use the same process to generate a hand of cards in a nice looking spread on a page in Scribus all ready for printing off. This script is based on the script outlined in this article: A Scribus Script to Distribute Images Across Page
So here are the scripts I developed. They are not all that user friendly but easy to modify to suit your own purposes. They are designed to run on a bunch of text files sitting in the same directory as the script.
The scripts are automatic once they have been set going and so any files that need to be included need to be defined in the scripts themselves.
The files the scripts use to load content from are;
These are a text list of story elements. Each line is a separate story element. For instance here is a fragment from the
So you can see from this example that serious stories are probable not going to be that common.
For the Scribus script there are some corresponding files for the background images. These were all strictly sized to fit the layout used in Scribus. Again, please refer to this article: A Scribus Script to Distribute Images Across Page
Standalone Python Script
The script that can be used with any python installation is listed below. You can download it from here: StoryCard_Deallerv2.py
# StoryCard_Deallerv2.py # The following is a small utility to deal out a selection of cards from the # Story Soup deck. import os import random CardCollection =  # List to contain all the story cards. fnames = ["Challenges.txt","Characters.txt","Events.txt","Locations.txt","Objects.txt"] # List containing the source filenames for the different card types. CardItems = len(fnames) for CardType in range(0,CardItems): WorkingFile = open(fnames[CardType],"r") Filelines = WorkingFile.readlines() WorkingFile.close for line in Filelines: CardCollection.append([CardType,line]) # At this stage we should have a list with all of the cards and their type appended. We need a seperate # list for the ending cards. EndingList =  WorkingFile = open("Endings.txt","r") Filelines = WorkingFile.readlines() WorkingFile.close for line in Filelines: EndingList.append(line) StoryCardNo = 8 # Number of story cards to deal EndingCardNo = 2 # Number of ending cards to deal. StorySelection = random.sample(CardCollection,StoryCardNo) EndingSelection = random.sample(EndingList,EndingCardNo) print(StorySelection) print(EndingSelection) #Output this to a new text file. DealtCardsFile = open("DealtCards.txt","w") DealtCardsFile.writelines("Story Cards\n") for line in StorySelection: CardCategory = fnames[line] CardCat = CardCategory.split(".") CCateg = CardCat + ": " Entry = CCateg + line DealtCardsFile.writelines(Entry) DealtCardsFile.writelines("\n\n") DealtCardsFile.writelines("Endings\n") DealtCardsFile.writelines(EndingSelection) DealtCardsFile.close()
The way it works is that it loads the contents from each text file (except
Endings.txt) into a single list together with a number that represents the type of card. It does the same with the ```Endings.txt`` but into a separate list.
From those lists it randomly selects a defined number of story element cards and ending cards and displays these in the terminal as well as writing them to a new text file. The two lines used to define how many cards are selected are;
StoryCardNo = 8 # Number of story cards to deal EndingCardNo = 2 # Number of ending cards to deal.
Here are two examples of the output file content;
Story Cards Challenges: They were stuck. Characters: A golem made from something discarded. Locations: a spaceship Locations: An alternate plane / the afterlife etc Events: A competition is won Events: A summoning / summons Events: a chase Objects: Container Endings He saw the error in his ways and continued with even greater enjoyment. When she put it on, everyone bowed their heads and submitted to her.
and another deal.
Story Cards Objects: a bomb Objects: A painting Challenges: They were bored Events: A treasure is discovered Challenges: ... misled Events: A project is completed Challenges: ... disaster will occur if one of your characters gets hungry. Objects: Underwear Endings They signed the deal then realised their mistake The mysterious stranger rode off into the sunset, their final words hanging behind them "That was the wrong question."
Do they sound like starters for stories to you? Yep. I think so too. The first one looks like it would be a pretty daft story, but the second one has the potential to be a bit more edgy …with a bit of work.
The Scribus Script
The script above is the heart of this script. The difference is the use of the Scribus python functions to distribute the text around the page and place the appropriate background images for each card type. The script works in Scribus 1.4.3. I have yet to try it in the new Scribus 1.5. Depending on the fonts you have loaded on your machine you may need to alter line 121
scribus.setFont('Algerian Regular',frame) to one of your installed fonts - e.g.
Download the script from here: StoryCard_DeallerScribusv0.py
#!/usr/bin/env python """ StoryCard_DeallerScribusv0.py The following is a small utility to deal out a selection of cards from the Story Soup deck. This variation uses an index rather than the Card type name The script then pulls up the appropriate background image and drops them into A sheet of 10 cards. You will need to ensure there are enough pages in your document to hold all of the cards you generate. @author: Hamish Trolove @website: www.techmonkeybusiness.com @copyright Creative Commons - by nc sa """ import os import random import sys try: import scribus except ImportError: print ("This script only runs from within Scribus.") sys.exit(1) try: from PIL import Image except ImportError: print ("Unable to import the Python Imaging Library module.") sys.exit(1) CardCollection =  # List to contain all the story cards. fnames = ["Challenges.txt","Characters.txt","Events.txt","Locations.txt","Objects.txt"] # List containing the source filenames for the different card types. Imgnames = ["Challenges.jpg","Characters.jpg","Events.jpg","Locations.jpg","Objects.jpg","Endings.jpg"] #List of the background image names for the corresponding card types. CardItems = len(fnames) multTx = 0 # Multiplier for the column position multTy = 0 # Multiplier for the row position pageInd = 1 # Page number w = 55 #Width of Image frame h = 90 #Height of Image frame scribus.gotoPage(pageInd) # Make sure it always starts from first page StoryCardNo = 8 # Number of story cards to deal EndingCardNo = 2 # Number of ending cards to deal. NumCards = StoryCardNo + EndingCardNo #Number of cards to insert. for CardType in range(0,CardItems): WorkingFile = open(fnames[CardType],"r") Filelines = WorkingFile.readlines() WorkingFile.close for line in Filelines: CardCollection.append([CardType,line]) # At this stage we should have a list with all of the cards and their type appended. We need a seperate # list for the ending cards. EndingList =  WorkingFile = open("Endings.txt","r") Filelines = WorkingFile.readlines() WorkingFile.close for line in Filelines: EndingList.append([5,line]) StorySelection = random.sample(CardCollection,StoryCardNo) EndingSelection = random.sample(EndingList,EndingCardNo) print(StorySelection) print(EndingSelection) StorySelection.extend(EndingSelection) # Now we create the Scribus page(s). This is done by reading StorySelection and EndingSelection # and using the indexes in them to find the appropriate background image. for EntryCd in StorySelection: #Each entry will be another list with the index and card text. if multTy > 1: multTy = 0 multTx = 0 pageInd = pageInd + 1 scribus.gotoPage(pageInd) x = 11 + w * multTx #first corner is 11mm across. y = 15 + h * multTy #first corner is 15mm down. # create an image frame and put the image into it #The business card dimensions are known and so we are looking to drop image into this size frame. ImageFrame = scribus.createImage(x, y, w, h) #BkgndImg = Image.open(Imgnames[EntryCd]) #Pull out the index and use it to get the image file name. scribus.loadImage(Imgnames[EntryCd], ImageFrame) scribus.setScaleImageToFrame(True, False,ImageFrame) scribus.setFillColor("None", ImageFrame) scribus.setLineColor("None", ImageFrame) scribus.selectObject(ImageFrame) scribus.moveSelectionToBack() scribus.deselectAll() #BkgndImg.close() #Now add the text over the top. frame = scribus.createText(x+7.5, y+35, w-15, h-30) text = unicode(EntryCd, 'iso-8859-2') #Pull out the text for the selected card. scribus.setText(text, frame) scribus.setTextAlignment(1,frame) # ALIGN_CENTERED = 1 scribus.setFont('Algerian Regular',frame) scribus.setFontSize(14,frame) scribus.setLineSpacing(12,frame) scribus.selectObject(frame) scribus.moveSelectionToFront() scribus.deselectAll() # Control to index around the page. if multTx > 3: multTy = multTy + 1 multTx = 0 x = 11 else: multTx = multTx + 1
The output is a Scribus document which can easily be turned into a pdf.
To use this script, start a new document with a A4 page in a landscape orientation. In this case the margin are 11mm on the left and right and 15mm on the top and bottom.
Run the script by going to Scripts in the top menu bar and Execute Script. Navigate to the
StoryCard_DeallerScribusv0.py which will need to be in the same directory as your story element files, and hit “OK”.
Crash! Bang! Wollop! We have our spread of cards. The original card designs were not done with an automated system laying out the text in mind, and so there is a bit of realignment needed – or more to the point I should standardise the layout between card types. But whatever, the script does it’s job.
So here is an example output.
I think I would struggle to get anything out of this spread.
Anyway, I hope this is useful at least as a basis for someone else’s card dealler, story shuffler.
OK, so as an amusing aside here is a little story I wrote using the following spread of cards dealt by the Scribus version of the script.
and the story created using these cards is available here or click on the image below to open the pdf version of the story;
The stuff on this page is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.