Thursday, May 24, 2007 is 99% back is 99% back. The only thing not working is my email me page; some permissions got changed and I may have to implement Blowfish encryption in PHP to get this page to work again.

    I have uploaded MaraDNS 1.3.05 and Daniel's Slackware port of MaraDNS to the web page.

    My current project for the next version of MOAM-CD is the have difficulty levels implemented in the Freecell game. So far, I have standardized the shuffling code to always shuffle a given hand when given a certain RNG seed. The next step after that was to standardize the RNG used, so that the same hand is given, regardless of operating system. The RNG code is as follows:

    /* Public domain; this generates a freecell hand
    * suitable for use by fc-solve (A Freecell solver)
    * that is the same as the freecell hand
    * generated by the version of Ace of Penguins
    * that I have hacked to always generate the
    * same hand with a given seed
    * Usage is straightforword:
    ./gen_hand | fc-solve
    * Where is the seed for the freecell
    * hand in question */


    static uint32_t n = 0;
    int deck[52];

    uint32_t zrand(void) {
    uint64_t z;
    z = n;
    /* These numbers are from page 6 of "Tables
    * of Linear Congruential Generators of
    * Different Sizes and Good Lattice
    * Structure" by Pierre L'Ecuyer */
    z *= 279470273;
    z %= 4294967291U;
    n = z;
    return (int)(n & 0x7fffffff);

    void deck_init() {
    int a;
    for(a=0;a<52;a++) {
    deck[a] = a;

    void deck_shuffle(uint32_t seed) {
    int a, b, c;
    n = seed;
    for(a = 0; a< 52; a++) {
    b = (zrand() % (52 - a)) + a;
    c = deck[b];
    deck[b] = deck[a];
    deck[a] = c;

    char *num_to_card(int card) {
    char *out;
    int a;
    char suit[4] = {'H', 'D', 'C', 'S'};
    char face[13] = {'A', '2', '3', '4', '5',
    '6', '7', '8', '9', '0', 'J',
    'Q', 'K'};
    out=(char *)malloc(4);
    if(card >> 2 == 9) {out[0] = '1'; a = 1; }
    else { a = 0; }
    out[a++] = face[card >> 2];
    out[a++] = suit[card % 4];
    out[a] = '\0';
    return out;

    int main(int argc, char **argv) {
    int a, b;
    char *c;
    int s;
    if(argc != 2) { s = 394; }
    else { s = atoi(argv[1]); }
    for(a=0;a<4;a++) {
    for(b=0;b<7;b++) {
    c =
    num_to_card(deck[51 - a - (b * 8)]);
    printf("%s ", c);
    for(a=0;a<4;a++) {
    for(b=0;b<6;b++) {
    c =
    num_to_card(deck[47 - a - (b * 8)]);
    printf("%s ", c);

    The next step is to run a large number of hands through a freecell solver in order to see how many freecells it takes to solve a given hand. A hand that can be solved with 0 freecells is a novice hand. A hand that needs 1 freecell to solve is an easy hand; 2 freecells (the most common) is a medium hand; 3 freecells is a hard hand; 4 an expert hand; and more than 4 is an impossible hand.

    As of this morning before I left home to go to work, it found five novice hands (116, 497, 1195, 1762, and 2330), 438 easy hands, 1557 medium hands, 549 hard hands, 44 expert hands, and 16 hands that it thinks are impossible. I am sure some of the "impossible" hands are, in fact, solvable. For example, the Freecell solver couldn't solve hand 30:

    2D 3H 3D 9S 8S 3C JD
    AD 7H 2H 4D 6H KC KD
    JH QD 8C QH 5C 8D KH
    9D JC 5H TC 5D AC QS
    TD 3S AS 9C 4C TH
    4S AH 9H QC KS 7D
    6D 7C 2S 5S 6C 6S
    TS 8H JS 2C 7S 4H

    Here are some other hands the solver could not solve:

    KH TH AH 2D QC 6D 7D
    TS 6S 5S QH 9C 4S KS
    3D 5C AS 7C 8S JD 5H
    9S KD 2C 2S 3H 9H JS
    TC 8H QS 8D 9D AD
    4C JH AC 3S QD KC
    TD 5D 6H 4D 3C 6C
    2H JC 7H 8C 4H 7S

    7D JH TD 2C 9H 4D 6S
    TS 9C 3S 2H AD 4C 6C
    QS TH 7S QC 2S 8C KD
    KH 7H 5D AH QH JD 9S
    6H 5H JS 8D 4H 5S
    4S TC KC 2D KS 5C
    AS AC 9D QD JC 7C
    8S 8H 6D 3H 3C 3D

    KS 2C 3S 6H 6S QH 6C
    7S 3H KH JH 7C QS 3C
    7H 7D 9H 5C TD 8C AD
    4H 8D 4D JD AH TS 4S
    6D 4C 2D 9S TH 9C
    QD 9D 5S 3D TC 2H
    JS 2S 5D JC 8H 5H

    TS 5D 6S 3D 4S 7H 6D
    QD JH 7D 8C 2C TD JD
    KD 9S 9H QS QC 9D 5C
    8H JS 8D QH AD 6H KH
    5S 9C AS 6C KC KS
    2D 2H AC 2S 3C 3H
    TC 5H 8S 4D 4C 4H
    3S AH 7S JC TH 7C

    9H 4D 4S 2C 8H JC 6H
    3D QC QS 3S AC KC 2H
    5C 7C 8S 8D 6D 4C TD
    5S 8C JD QD KD TS AD
    AS KH 6C 2D 5H 7S
    AH KS 4H 9S 6S 7D
    7H 5D 2S TC 3C JH
    9C TH QH 3H 9D JS

    QC AC JD AS 3H 2C 7S
    3D 3C KD 5S 6S TD 7H
    3S QS 7C AH 4H 8S 6C
    4D 9C 2H 9S KH 8C QH
    JC AD 8H JH 6H TC
    8D QD 5D 9D 4S KC
    JS 4C 5C 5H KS TS
    6D 7D 2D TH 2S 9H

    8D AH 4S QD 7H 3H 8C
    KD JH 5D 2D KC 3C 9D
    5S 6S JC AD TH 7S QS
    2H 5C AC QH TD 8H 6H
    4H 3D KH 8S 2S 5H
    2C QC JD AS 6C 4D
    3S 6D KS TS JS 4C
    7D 9H 9C 7C TC 9S

    5H 2D 8H JS 4H JH QH
    6H 7S 5D 7C 4S 2H 9D
    6S TD 7H TC 7D 3C 2S
    QS 5C 9S 3D AH JC 8S
    2C 3S 9H JD KC 6C
    6D QD QC KH 8D 5S
    9C KS AC 3H TH 4C
    KD 8C AS AD TS 4D

    My laptop, at home, has been spending all day solving hands. It will take the laptop about a week to give me the 65000 hands I want to have.