/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/8kFa
*/
package
{
import com.bit101.components.Label;
import com.bit101.components.NumericStepper;
import com.bit101.components.TextArea;
import com.bit101.components.VBox;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.Dictionary;
/**
* Counting number of cardgame path combinations for Saboteur version 1.
* I'll do up a 3d version preview soon as I have a 3d model prepared!
* @author Glenn Ko
*/
public class SaboteurJetty extends Sprite
{
// standard mask values (fill regions paths)
public static const EAST:uint = (1 << 0);
public static const NORTH:uint = (1 << 1);
public static const WEST:uint = (1 << 2);
public static const SOUTH:uint = (1 << 3);
public static const NORTHEAST:uint = (1 << 0);
public static const NORTHWEST:uint = (1 << 1);
public static const SOUTHWEST:uint = (1 << 2);
public static const SOUTHEAST:uint = (1 << 3);
public static const NORTH_EAST:uint = (NORTH | EAST);
public static const NORTH_WEST:uint = (NORTH | WEST);
public static const SOUTH_WEST:uint = (SOUTH | WEST);
public static const SOUTH_EAST:uint = (SOUTH | EAST);
public static const ARC_VERTICAL:uint = (1 << 0);
public static const ARC_HORIZONTAL:uint = (1 << 1);
public static const ARC_NORTH_EAST:uint = (1 << 2);
public static const ARC_NORTH_WEST:uint = (1 << 3);
public static const ARC_SOUTH_WEST:uint = (1 << 4);
public static const ARC_SOUTH_EAST:uint = (1 << 5);
public static const ARC_MASK:uint = ~15;
static public const ARC_SHIFT:uint = 4;
// predicted: 2^5 (standard 90deg east,north,west,south,center mask) = 32
// + 8 (diagonal steer bendey cards, 2 steering mirrors and 6 with-orphan portions included)
// + 6 (vertical flip cases of diagonal steer bendey cards above 8-2=6, since 2 steering mirrors can't flip vertically) +
// + 6 ( horizontal and vertical striaght road with stray bit at side)
// TODO: Must provide visual support for vertical straight road gaps to horizontal neighbors
// + 4 (t junction with orphan edge bit)
// -1 (empty standard case)
// -1 (standard center cell only filled ) = 54
// -4 (standard single edge with center filled) (merely deeper end, achieves same purpose)
// = 50!
private var combinations:Vector.<uint> = new Vector.<uint>();
public function SaboteurJetty()
{
collectNumCombinations();
addChild(_previewJetty = new PreviewJetty());
createStepper();
_previewJetty.x = 10;
_previewJetty.y = 10;
}
private function createStepper():void
{
var stepper:NumericStepper;
var vLayout:VBox = new VBox(this, 128);
vLayout.x = 128;
var label:Label = new Label(vLayout, 0, 0, (combinations.length) + " found.");
stepper = new NumericStepper(vLayout, 0, 0, onStep);
stepper.minimum = 0;
stepper.maximum = combinations.length - 1;
stepper.value = 0;
debugField = new TextArea(vLayout);
onStep(null, stepper);
}
private function onStep(e:Event, stepper:NumericStepper=null):void
{
var stepper:NumericStepper = e ? (e.currentTarget as NumericStepper) : stepper;
var value:uint = combinations[ stepper.value ];
var debugStr:String = "";
debugStr += (value & EAST) ? "E " : "";
debugStr += (value & NORTH) ? "N " : "";
debugStr += (value & WEST) ? "W " : "";
debugStr += (value & SOUTH) ? "S " : "";
var arcValue:uint = (value & ARC_MASK) >> ARC_SHIFT;
debugStr += (arcValue & ARC_VERTICAL) ? "vert " : "";
debugStr += (arcValue & ARC_HORIZONTAL) ? "horiz " : "";
debugStr += (arcValue & ARC_NORTH_EAST) ? "ne " : "";
debugStr += (arcValue & ARC_NORTH_WEST) ? "nw " : "";
debugStr += (arcValue & ARC_SOUTH_WEST) ? "sw " : "";
debugStr += (arcValue & ARC_SOUTH_EAST) ? "se " : "";
debugField.text = debugStr;
var n:int = _previewJetty.numChildren;
while (--n > -1) {
var c:DisplayObject = _previewJetty.getChildAt(n);
c.visible = visJetty(value, c.name, stepper.value);
}
}
private var arcEdgeDict:Dictionary = new Dictionary();
private var _previewJetty:Sprite;
private function getArcConnectionMaskValues2():Vector.<uint> { // 12 hardcoded arc combinations
var vec:Vector.<uint> = new <uint>[ // setup lookup table of 6 possible connections to check
// 0,
(ARC_VERTICAL),
(ARC_HORIZONTAL),
(ARC_VERTICAL | ARC_HORIZONTAL),
(ARC_NORTH_WEST | ARC_SOUTH_WEST),
(ARC_NORTH_EAST | ARC_SOUTH_EAST),
(ARC_NORTH_WEST | ARC_NORTH_EAST), // 5 - start use 90 degree junction
(ARC_SOUTH_WEST | ARC_SOUTH_EAST),
(ARC_NORTH_EAST),
(ARC_NORTH_WEST),
(ARC_SOUTH_WEST),
(ARC_SOUTH_EAST), // 10 - end use 90 degree junction
(ARC_NORTH_WEST | ARC_SOUTH_EAST),
(ARC_SOUTH_WEST | ARC_NORTH_EAST )
];
var result:uint;
var len:int = vec.length;
for (var i:int = 0; i < len; i++) {
var value:uint = vec[i];
result = 0;
result |= (value & ARC_VERTICAL) ? (NORTH | SOUTH) : 0;
result |= (value & ARC_HORIZONTAL) ? (WEST | EAST) : 0;
result |= (value & ARC_NORTH_EAST) ? (NORTH | EAST) : 0;
result |= (value & ARC_NORTH_WEST) ? (NORTH | WEST) : 0;
result |= (value & ARC_SOUTH_WEST) ? (SOUTH | WEST) : 0;
result |= (value & ARC_SOUTH_EAST) ? (SOUTH | EAST) : 0;
arcEdgeDict[value] = result;
}
//throw new Error(vec);
return vec;
}
//private var arcValueList:Array = []; // for debuggign
private var debugField:TextArea;
private function collectNumCombinations():void
{
var dict:Dictionary = new Dictionary();
var vec:Vector.<uint> = getArcConnectionMaskValues2();
var key:uint;
var count:uint = 0;
for (var i:uint = 1; i < 16; i++) { // go through activatable east,north,west,south edge states
for (var a:uint = 0; a < vec.length; a++) { // go through all activable arc combinations
var arcValue:uint = vec[a];
var mask:uint = arcEdgeDict[arcValue];
if ( (i & mask) != 0 && (i & mask) === mask ) { // case with valid connectable arc combination
key = (arcValue << ARC_SHIFT) | i;
//if (key == 0) throw new Error("WRONG1");
if (dict[key] == null) {
dict[ key] = count++;
combinations.push(key);
// arcValueList.push(arcValue);
}
}
// case without any connecting arc
///*
key = i;
//if (key == 0) throw new Error("WRONG2");
if (dict[key] == null) {
dict[ key] = count++;
combinations.push(key);
// arcValueList.push(0);
}
// */
}
}
}
private function visJetty(value:uint, groupName:String, index:int):Boolean {
var arcValue:uint = (value & ARC_MASK) >> ARC_SHIFT;
//if (arcValue != arcValueList[index]) throw new Error("MISMATCH!:"+arcValue + ", "+arcValueList[index]);
var edgeValue:uint = value & ~ARC_MASK;
var top90Deg:Boolean = arcValue === (ARC_NORTH_WEST | ARC_NORTH_EAST) || (arcValue === (ARC_NORTH_EAST) && edgeValue===NORTH_EAST) || (arcValue === (ARC_NORTH_WEST) && edgeValue === NORTH_WEST);
var bottom90Deg:Boolean = arcValue === (ARC_SOUTH_EAST | ARC_SOUTH_WEST) || (arcValue === (ARC_SOUTH_EAST) && edgeValue === SOUTH_EAST) || (arcValue === (ARC_SOUTH_WEST) && edgeValue===SOUTH_WEST);
// /*
switch (groupName) {
case "side0":
case "side0_posts":
return ( value & EAST )!=0;
case "side1":
case "side1_posts":
return ( value & NORTH )!=0;
case "side2":
case "side2_posts":
return ( value & WEST )!=0;
case "side3":
case "side3_posts":
return ( value & SOUTH )!=0;
case "center":
return ((arcValue & (ARC_VERTICAL | ARC_HORIZONTAL))!=0) || top90Deg || bottom90Deg;
case "center_top":
return (arcValue & ARC_VERTICAL)!=0 || top90Deg; // has cut thru or T junction from bottom
case "center_bottom":
return (arcValue & ARC_VERTICAL)!=0 || bottom90Deg; // has cut thru or T junction from bottom
case "corner0_turn":
return (arcValue & ARC_NORTH_EAST)!=0 && !top90Deg; // and doesn't have T junction from top
case "corner1_turn":
return (arcValue & ARC_NORTH_WEST)!=0 && !top90Deg;
case "corner2_turn":
return (arcValue & ARC_SOUTH_WEST)!=0 && !bottom90Deg; // and doesn't have T junction from bottom
case "corner3_turn":
return (arcValue & ARC_SOUTH_EAST)!=0 && !bottom90Deg;
///*
case "corner0_railing":
return (arcValue & ARC_NORTH_EAST)!=0 && top90Deg;
case "corner1_railing":
return (arcValue & ARC_NORTH_WEST)!=0 && top90Deg;
case "corner2_railing":
return (arcValue & ARC_SOUTH_WEST)!=0 && bottom90Deg;
case "corner3_railing":
return (arcValue & ARC_SOUTH_EAST)!=0 && bottom90Deg;
//*/
default: return false;
}
// */
///return false;
}
}
}
import flash.display.Shape;
import flash.display.Sprite;
class PreviewJetty extends Sprite {
public function PreviewJetty() {
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, 3 * 32, 5 * 32);
createShape("side0", 2, 2);
createShape("side1", 1, 0);
createShape("side2", 0, 2);
createShape("side3", 1, 4);
createShape("center", 1, 2);
createShape("center_top", 1, 1);
createShape("center_bottom", 1, 3);
createShape("corner0_turn", 4, 3, true);
createShape("corner1_turn", 1, 3, true);
createShape("corner2_turn", 1, 6, true);
createShape("corner3_turn", 4, 6, true);
}
private function createShape(name:String, x:int, y:int, halfSize:Boolean=false):void {
var gridSize:Number = halfSize ? 16 : 32;
var shape:Shape = new Shape();
shape.name = name;
shape.graphics.lineStyle(1, 0xFFFFFF);
shape.graphics.beginFill(0xFF0000);
shape.graphics.drawRect(x * gridSize, y * gridSize, gridSize, gridSize);
addChild(shape);
}
}