Status of Projects
Flash object info dumper: having a bit of trouble. I’m stuck; I cannot figure out how to use a string naming a variable of an object and getting the value out of it. I thought that the variables could be accessed as in an associative array, but that is not the case. Also, getting at the properties of an associative array cannot be done through the describeType() method. So I would very much appreciate some advice towards doing this; then I will be not far from finishing this project.
I have started another project, called Conjure (for now). It generates files (and directory hierarchies) from templates, and it uses various means to get information. Hopefully, I’ll have enough code put together soon that I’ll feel ready to put it up somewhere. I may even try to explain the idea better tomorrow.
UPDATE: I just realized, I forgot to mention that Conjure is written in Ruby. A very important bit of info. Also, I am trying out test-based development.
ActionScript 3 Dice Poker Hand Evaluator
So, here is a class I wrote today. Jesse Freeman asked me to do this project, so I did. He showed me the approach that this class uses for being a singleton.
/**
* <p>Original Author: aidan coyne</p>
* <p>Class File: PokerLogic.as
*
* <p>Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:</p>
*
* <p>The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.</p>
*
* <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.</p>
*
* <p>Licensed under The MIT License</p>
* <p>Redistributions of files must retain the above copyright notice.</p>
*
* <p>Revisions<br/>
* 0.1 Initial version Aug 28, 2008</p>
*
*/
package //com.wordpress.raptros
{
/** written by (raptros-v76) Aidan Coyne while working at @radical.media.
*/
//import flash.display.Sprite; //this isn't actually a sprite.
/** Logic singleton for a simple poker dice game.
* At first I intended to do a lookup table system
* but I soon learned I would have to hand write every combination.
* No. Instead, I did this.
*/
public class PokerLogic //extends Sprite //not anymore!
{
private static var __instance:PokerLogic;
private static var __primes:Array = new Array(2, 3, 5, 7, 11, 13);
/** this is supposed to be a singleton
*
*/
public function PokerLogic(enforcer:SingletonEnforcer)
{
}
public static function get instance():PokerLogic //use this to get an`instance of PokerLogic.
{
if(PokerLogic.__instance == null)
{
PokerLogic.__instance = new PokerLogic(new SingletonEnforcer());
}
return PokerLogic.__instance;
}
/** @param hand1 array containing dice rolls
* @param hand2 array containing dice rolls
* @return 1 for hand1, 2 for hand 2, 0 if tied
*/
public function compareHands(hand1:Array, hand2:Array):int
{
var rank1:Object = rankHand(hand1);
var rank2:Object = rankHand(hand2);
if (rank1.rank == rank2.rank)
return 0;
else if (rank1.rank > rank2.rank)
return 1;
else
return 2;
}
/** @param hand array containing dice rolls
* @return an object ranking the hand.
* first number (object.rank) will be between 16 and 6 hundred million
* under 100:high card; 1000 to 7000: 1 pair
* 10,000 to 70,000: 2 pairs; 100,000 to 700,000; 3 of a kind
* 1,000,000 to 7,000,000: full house; 8,000,000 or 9,000,000: straight
* 10,000,000 to 70,000,000: 4 of a kind;
* 100,000,000 to 600,000,000: 5 of a kind.
* second number (object.type) see findHandType
*/
public function rankHand(hand:Array):Object
{
//count number of each type of card
var counts:Array = new Array(0, 0, 0, 0, 0, 0);
for each (var card:int in hand)
{
counts[card - 1]++;
}
var type:int=findHandType(counts);
var rank:int=0;
switch (type)
{
case 0: //high card
for (card=0; card < counts.length; card++)
{
//in high card, there are no repeats
if(counts[card] == 1)
rank+=card;
}
break;
case 1: //1 pair
rank=rankOnePair(counts);
break;
case 2: //2 pairs
rank=rankTwoPairs(counts);
break;
case 3: //3 of a kind
rank=rankThree(counts);
break;
case 4: //full house
rank=rankFullHouse(counts);
break;
case 5: //straight
rank=rankStraight(counts);
break;
case 6: //4 of a kind
rank=rankFour(counts);
break;
case 7: //5 of a kind
rank=rankFive(counts);
break;
}
return {rank:rank, type:type};
}
/** finds the type of the hand: (going from 0 to 7)
{high card, 1 pair, 2 pair, 3kind, fullhouse, straight, 4kind, 5kind}
*/
private function findHandType(counts:Array):int
{
var flags:Array= new Array(1, 0, 0, 0, 0, 0, 0, 0);
var ones:int=0;
for (var die:int = 1; die <= counts.length; die++)
{
var diceCount:int = counts[die-1];
switch(diceCount)
{
case 1:
ones++;
break;
case 2:
if (flags[1] > 0)
flags[2]++;
if (flags[3] > 0)
flags[4]++;
flags[1]++;
break;
case 3:
if (flags[1] > 0)
flags[4]++;
flags[3]++;
break;
case 4:
flags[6]++;
break;
case 5:
flags[7]++;
break;
}
}
//test for a straight
if (ones == 5)
{
if (counts[0] == 0 || counts[counts.length -1] == 0)
flags[5]++;
}
for (var flag:int = flags.length - 1; flag >= 0; flag--)
{
if (flags[flag] > 0)
{
return flag;
}
}
return -1; //should not be reached. might be a good idea to actually test for...
}
private function rankOnePair(counts:Array):int
{
var rank:int=0;
var multi:int=1;
//using the primes trick, plus knowledge that non-pair cards
// are unique in hand
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 1)
multi *= PokerLogic.__primes[card-1];
else if (counts[card-1] == 2)
rank = card * 1000;
}
rank += multi;
return rank;
}
private function rankTwoPairs(counts:Array):int
{
var rank:int=0;
var multi:int=0;
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 1)
multi = card;
else if (counts[card-1] == 2)
{
if (rank > 0)
rank += card*10000;
else
rank +=card*1000;
}
}
rank += multi;
return rank;
}
private function rankThree(counts:Array):int
{
var rank:int=0;
var multi:int=1;
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 1)
multi *= PokerLogic.__primes[card-1];
else if (counts[card-1] == 3)
rank = card * 100000;
}
rank += multi;
return rank;
}
private function rankFullHouse(counts:Array):int
{
var rank:int=0;
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 3)
rank+=card*1000000;
else if (counts[card-1] == 2)
rank+=card*100000;
}
return rank;
}
private function rankStraight(counts:Array):int
{
var rank:int=8000000;
if (counts[0] == 0)
rank=9000000;
return rank;
}
private function rankFour(counts:Array):int
{
var rank:int=0;
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 4)
rank+=card*10000000;
else if (counts[card-1] == 1)
rank+=card;
}
return rank;
}
private function rankFive(counts:Array):int
{
var rank:int=0;
for (var card:int=1; card<=counts.length; card++)
{
if (counts[card-1] == 5)
rank+=card*100000000;
}
return rank;
}
}
}
//singleton stuf borrowed from Jesse Freeman over at flashartofwar.com
internal class SingletonEnforcer { }
Here is a test class.
package
{
import flash.display.Sprite;
public class DicePokerTest extends Sprite
{
public function DicePokerTest()
{
var types:Array = new Array("High Card", "One Pair", "Two Pair", "Three of a Kind", "Full House", "Straight", "Four of a Kind", "Five of a Kind");
var logic:PokerLogic=PokerLogic.instance;
for (var run:Number=0; run < 5; run++)
{
trace("Test " + run);
var hand1:Array = makeRandomHand();
var hand2:Array = makeRandomHand();
var rank1:Object = logic.rankHand(hand1);
var rank2:Object = logic.rankHand(hand2);
trace("Hand 1: " + hand1 +" has value: " + rank1.rank + ", and is a " + types[rank1.type]);
trace("Hand 2: " + hand2 +" has value: " + rank2.rank + ", and is a " + types[rank2.type]);
var winner:Number=logic.compareHands(hand1, hand2);
trace("Winner is hand"+winner);
}
}
private function makeRandomHand():Array
{
var hand:Array = new Array(diceRoll(), diceRoll(), diceRoll(), diceRoll(), diceRoll());
return hand;
}
private function diceRoll():int
{
return ((Math.random()*1000)%6)+1;
}
}
}
Enjoy.
Objective-C Part 1: the Basics of Objects and Classes
So, I have been asked to write a post explaining Objective-C. Objective-C is not an easy language to learn; I learned it by reading the several hundred paged language documentation on the Apple iPhone developer website. Yes, I did it in an afternoon, but it was not an easy afternoon. Objective-C is difficult because of what it is: a layer built on top of C; it cannot use syntax that would conflict with the existing C syntax. Objective-C is also, apparently, a dynamic language. The design of Objective-C is very different from, say, ActionScript or Java. I’m not sure how to really go about explaining this language, as I do not really have any good ideas for a tutorial project. I guess I can try to do this as a series of posts, and so, I will start with the basic concept of objects in this language.
Read more…
Ant and template based generation.
Ant, the java based build system, is pretty cool. I’ve been working on a template based project setup system.
Here is how.
- You’ll need a templates directory to keep all of the templates you want to generate
- Put together a ant build xml file that has a task to make the directory structure
- Now for the generation: use the Copy task to copy a template from the template directory to whatever file it should be in the project.
- Put a filterset subtask inside the copy. For each token, represented by default as @TOKENNAME@ (in the template files), use a filter task (with token=”TOKENNAME” value=”whatever you want”) to replace @TOKENNAME@ with whatever you want to have in there, such as class names, etc.
There you go.
New post over at STR.
Fairly political. Not for the faint of heart (or mind). “A Revolution to Save America”
SocketServer fail.
Technically, I should have known better. I thought I had a plan to solve the problem I described earlier.
My idea was towards the end of using python’s SocketServer to create a queue based control provider; i.e, people could connect to the server, and would enter a queue for getting 60 seconds of control over the missile launcher. My plan was to give hand the TCPSocketServer initializer a method that when called, would return a special request handler object that had been either put into a queue or given control; this request handler would then be controllable from the control object that stored it. That way, I would be able give the handler control of the missiles after going through the queue.
The fail came when I discovered that the constructor of a socket server request handler calls all of its processing functions inside itself: the job of running the request finishes when the initializer finishes.
I plan to change my subclassed request handler so that it does not do the job of running the request, instead, the control object will do that job, so that I can thread the handle calls. Oh well.
Vim; build systems
Vim actually does work for flash development. The extension that makes it possible, along with all devel in vim, IMO, is the project plugin. The ant build system really helps, too; of course, it is difficult to remember that I need to rebuild the code every time I make a change, especially after using things like python and ruby. I’m going to really start investigating using build systems, most likely rake, for productivity stuff. Then, if I can tie that into vim, things will rock. Hard.
Argh.
Ok. Background: I am an intern at radical media. It is a fun internship, I have learned flash programming and broke an enormous mirror. Anyway, I am working on a project to control a USB missile launcher.
Here is the structure:
Linux system running inside parallels on a mac, called missile-launcher
missile-launcher runs my modifications of this program. My modifications change the way the network portion work to use a tcp system. This program is missile.py.
On another server, missilecommand, there is MissileControl.swf, which is a flash program that talks to missile.py on missile-launcher. MissileControl works nicely, however, next week, I am going to make it have a lock system, so only one person at a time will be able to control it. I still have to think about how to do this though.
I’ve also been tasked with writing an iPhone app to control this thing. I tried to do it as a web app, but javascript doesn’t do sockets, afaik. Oh well. I am going to have to learn objective-C.
Anyway, I was trying to use a python program called orbited to make a javascript socket proxy, but it doesn’t seem to work. Maybe I am not doing it right, maybe it doesn’t work the way I need it too. Now I have a headache from this.
comments