chewie-book

High Stakes -  A real account of what's happening in poker.
archive

When I was 6, every morning while I was eating cereal I would have a big Calvin and Hobbes book open in front of me. I never read it out of a newspaper, having to wait a whole day before the next little morsel, but we had these collection books full of strips that I could blow through like binge watching Netflix. There's no doubt a running narrative between the strips (some even continuing the same event) but each also exists as its own distinct story, like a joke in a comedy routine. This is why in researching and developing ideas for this project I was excited to find an online database containing plot descriptions of every published Calvin and Hobbes comic strip.

Thinking about the different uses of these texts, I was wondering what Calvin and Hobbes was at its lowest level and the types of events that transpired in the strip. Calvin is relentlessly true to himself and his beliefs despite the pressure he faces from his peers and superiors to act "normal": social rejection, being grounded, and getting scolded by his teachers to name a few. There's something admirable about the willingness to believe in yourself to that extent, but it also causes a great deal of inefficiency when you refuse to think based on observation or even speculation and only perpetuating and expanding on your existing ideas.

This is almost the complete opposite of some thoughts I've had about poker.

In this relentless game you are restricted to a finite set of actions, and (at least at the professional level) if you aren't able to make the most efficient set of actions based on the changing state of the game and the mechanisms of probability, you lose with no second chance. Because these two worlds are so contradictory I thought it would be interesting and amusing to combine references to both in these short, narrative descriptions.

I decided to use the texts by replacing the main characters with popular poker players, and replacing some of the Calvin and Hobbes language with poker terms. These terms were collected from an article describing all of the rules for playing no-limit Texas hold 'em. The results were interesting and at times amusing, although they definitely weren't completely coherent.

For the background images, my program went through each text, added each instance of a players name to a list and then used those frequency indices to select which player to show a picture of in the background. The front and back cover pages  are illustrations from one of the gorgeous full-color strips released on Sundays.

 

Code in Java for ripping summaries of every Calvin and Hobbes comic to a .txt file.

PrintWriter output;
 
 
void setup() {
  output = createWriter("positions.txt");
  String t;
  int max = 3150;
 
  output.println("{");
 
  for (int i=1; i<max+1; i++) {
    println(i);
    t = getJist(i);
    t = t.replace("\"","'");
 
    output.print("\""+str(i)+"\" : \"");
    output.print(t);
 
    output.print("\"");
    if (i<max) output.print(",");
    output.println("");
  }
  output.println("}");
  output.close();
}
 
String getJist(int n) {
  if ((n<1)||(n>3150)) return "invalid index";
  else {
    String[]t;
    t = loadStrings("http://www.reemst.com/calvin_and_hobbes/stripsearch?q=butt&search=normal&start=0&details="+str(n));
 
    String line = t[56];
    t = line.split(" "); line = t[1]; 
    return line; 
  }
}

Code in Javascript for modifying the texts and outputting to .json:

var t,p,corp, rm;
 
var availPos = ["nns","nn","jj"];//,"vbg","vbn","vb","vbz","vbp"];
 
 
 
var corp2 = {
  "nns": [],
  "nn": [],
  "jj": [],
  "vbg": [],
  "vbn": [],
  "vb": [],
  "vbz": [],
  "vbp": [],
  "rb": []
}
 
var nns = [];
var nn = [];
var jj = [];
var vbg = [];
var vbn = [];
var vb = [];
var vbz = [];
var vbp = [];
var rb = [];
 
 
 
 
var reps = [
  ["Calvin","Negreanu"],
  ["Hobbes","Dwan"],
  ["Mom","Selbst"],
  ["Dad","Ivey"],
  ["Susie", "Tilly"],
  ["Christmas", "WSOP"],
  ["parent", "sponsor"],
  ["Parent", "Sponsor"],
  ["Tiger", "Dealer"],
  ["tiger", "dealer"],
  ];
 
function preload() {
  t = loadJSON("jists.json");
  p = loadStrings("poker.txt");
}
 
function setup() {
  createCanvas(400, 400);
  //print("okay");
  loadToks();
  var texts = [];
  var fake;
  for (var i=0; i<3000; i++) { ttt = doer(int(random(3150))); fake = new RiString(ttt); fake.replaceAll("\"", ""); fake.replaceAll(" ,", ","); ttt = fake._text; texts.push(ttt); } var ret = {"a":texts}; saveJSON(ret,"all.json"); //print(availPos); } function draw() { background(220); } function doer(n) { var j = RiString(t[n]); for (var i in reps) { j.replaceAll(reps[i][0], reps[i][1]); } //print(j); return advRep(j._text); } function loadToks() { var movie = join(p," "); rm = new RiMarkov(3); var toks = movie.split(" "); var om,rs; var tooks = []; for (var i in toks) { if (toks[i].length>3) {
    	om = split(split(split(toks[i],".")[0],",")[0],"?")[0];
      //if (RiTa.isNoun(om)&& !(RiTa.isAdjective(om))) {
      rs = new RiString(om);
      rs = rs.replaceAll("(","");
      rs = rs.replaceAll(")","");
      rs = rs.replaceAll(":","");
      rs = rs.toLowerCase();
      rs = rs.trim();
    	var ppp = RiTa.getPosTags(rs._text)[0];
      if (availPos.indexOf(ppp)!=-1 ) {
        tooks.push(rs._text);
        corp2[ppp].push(rs._text);
      }
 
    }
    //print(toks[i]);
  }
  //print(corp2)
  //saveJSON(corp2,"corp2.json");
  rm.loadTokens(tooks);
}
 
function advRep(s) {
  var poss = RiTa.getPosTags(s);
  var toks = RiTa.tokenize(s);
  var stringy = "";
  var randInt;
  for (var i in toks) {
    if (availPos.indexOf(poss[i])!=-1 && int(random(3))==0) {
      randInt = int(random(corp2[poss[i]].length))
      if (!(RiTa.isVerb(toks[i])) || poss[i]=="vbg") {
        for (var j in poss) {
          if (toks[j] == toks[i]) toks[j] = corp2[poss[i]][randInt];
        }
      }
      else {
        for (var j in poss) {
          if (toks[j] == toks[i]) toks[j] = corp2[poss[i]][randInt];
        }
      }
 
    }
  }
  var stringgg = new RiString(join(toks, " "));
  stringgg.replaceAll(" .", ".");
  return str(stringgg._text);
 
}

Basil.js code:

#include "../../bundle/basil.js";
 
// Version for basil.js v.1.1.0
// Load a data file containing your book's content. This is expected
// to be located in the "data" folder adjacent to your .indd and .jsx.
// In this example (an alphabet book), our data file looks like:
// [
//    {
//      "title": "A",
//      "image": "a.jpg",
//      "caption": "Ant"
//    }
// ]
var jsonString;
var jsonData;
var text = ["*here is where I included the quotes*"];
];
 
//--------------------------------------------------------
function setup() {
  var randSeed = 2892;
  while (b.pageCount()>=2) b.removePage();
 
  // Load the jsonString.
  jsonString = b.loadString("lines.json");
 
  // Clear the document at the very start.
  b.clear (b.doc());
 
 
  var imageX = 72*1.5;
  var imageY = 72;
  var imageW = 72*4.5;
  var imageH = 72*4.5;
  var anImageFilename = "images/front.jpg";
 
  var anImage = b.image(anImageFilename, 35, 35, 432-35*2, 648-35*2);
  anImage.fit(FitOptions.FILL_PROPORTIONALLY);
 
  // Make a title page.
  b.fill(244, 215, 66);
  b.textSize(48);
  b.textFont("Calvin and Hobbes","Normal");
  b.textAlign(Justification.LEFT_ALIGN);
  b.text("CHEWIE", 60,540,360,100);
 
 
  // Parse the JSON file into the jsonData array
  jsonData = b.JSON.decode( jsonString );
  b.println(jsonData);
 
 
  // Initialize some variables for element placement positions.
  // Remember that the units are "points", 72 points = 1 inch.
  var titleX = 195;
  var titleY = 0;
  var titleW = 200;
  var titleH = 600;
 
  var captionX = 72;
  var captionY = b.height - 108;
  var captionW = b.width-144;
  var captionH = 36;
 
  var txt, tok, max;
 
  var just;
  var names = ["n"];
  // Loop over every element of the book content array
  // (Here assumed to be separate pages)
 
  for (var i = 0; i < 9; i++) { // Create the next page. b.addPage(); txt = text[randSeed+i]; tok = b.splitTokens(txt," "); for (var j=tok.length; j>=0; j--) {
      if (tok[j] === "Dwan"){
        names.push("d");
      }
      if (tok[j] === "Hellmuth") {
        names.push("h");
      }
      if (tok[j] === "Selbst") {
        names.push("s");
      }
      if (tok[j] === "Tilly") {
        names.push("t");
      }
      if (tok[j] === "Negreanu") {
        names.push("n");
      }
    }
 
    var ic = b.floor(b.random(0,names.length));
 
    ic = names[ic];
    names = [];
    if (ic == "d") max=6;
    if (ic == "h") max=7;
    if (ic == "i") max=11;
    if (ic == "n") max=9;
    if (ic == "s") max=6;
    if (ic == "t") max=3;
 
    anImageFilename = "images/"+ic + (i%max+1)+".jpg";
 
    // Load an image from the "images" folder inside the data folder;
    // Display the image in a large frame, resize it as necessary.
 // no border around image, please
 
 
 
    anImage = b.image(anImageFilename, 0, 0, 432, 648);
    anImage.fit(FitOptions.FILL_PROPORTIONALLY);
    b.opacity(anImage,70);
    if (i%2==0) {
      titleX = 50;
      just = Justification.LEFT_ALIGN;
    } else {
      titleX = 190;
      just = Justification.RIGHT_ALIGN;
    }
 
    b.textSize(16);
    b.fill(0);
 
    b.textFont("DIN Alternate","Bold");
    b.textAlign(just, VerticalJustification.BOTTOM_ALIGN  );
    var ttp = b.text(txt, titleX,titleY,titleW,titleH);
 
    // Create textframes for the "caption" fields
    b.fill(0);
    b.textSize(36);
    b.textFont("Helvetica","Regular");
    b.textAlign(Justification.LEFT_ALIGN, VerticalJustification.TOP_ALIGN );
    //b.text(jsonData."first"[0].caption, captionX,captionY,captionW,captionH);
 
  };
  b.addPage();
  imageX = 72*1.5;
  imageY = 72;
  imageW = 72*4.5;
  imageH = 72*4.5;
  anImageFilename = "images/back.jpg";
 
  anImage = b.image(anImageFilename, 35, 35, 432-35*2, 648-35*2);
  anImage.fit(FitOptions.FILL_PROPORTIONALLY);
}
 
// This makes it all happen:
b.go();