~keith-penguin/kdegames/trunk

« back to all changes in this revision

Viewing changes to kpat/patsolve/mod3.cpp

  • Committer: Keith Worrell
  • Date: 2009-03-18 05:35:28 UTC
  • Revision ID: keith.worrell@gmail.com-20090318053528-mx6x9c0ngmg0kg6p
imported project

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Common routines & arrays. */
 
2
 
 
3
#include "mod3.h"
 
4
#include "../mod3.h"
 
5
#include "../pile.h"
 
6
#include "../deck.h"
 
7
 
 
8
#include <cstdio>
 
9
#include <cstdlib>
 
10
#include <cstring>
 
11
#include <cctype>
 
12
#include <cmath>
 
13
#include <sys/types.h>
 
14
#include <cstdarg>
 
15
 
 
16
#include <kdebug.h>
 
17
 
 
18
/* These two routines make and unmake moves. */
 
19
 
 
20
#define PRINT 0
 
21
#define PRINT2 0
 
22
 
 
23
void Mod3Solver::make_move(MOVE *m)
 
24
{
 
25
#if PRINT
 
26
    if ( m->totype == O_Type )
 
27
        fprintf( stderr, "\nmake move %d from %d out %d (at %d)\n\n", m->card_index, m->from, m->to, m->turn_index );
 
28
    else
 
29
        fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index );
 
30
    print_layout();
 
31
#else
 
32
    //print_layout();
 
33
#endif
 
34
 
 
35
    int from, to;
 
36
    from = m->from;
 
37
    to = m->to;
 
38
 
 
39
    if ( from == deck )
 
40
    {
 
41
        int len = m->card_index;
 
42
        if ( len > 8 )
 
43
            len = 8;
 
44
        for ( int i = 0; i < len; i++ )
 
45
        {
 
46
            card_t card = *Wp[deck];
 
47
            Wlen[deck]--;
 
48
            Wp[deck]--;
 
49
 
 
50
            card = ( card & PS_SUIT ) + RANK( card );
 
51
            Wp[24 + i]++;
 
52
            Wlen[24 + i]++;
 
53
            *Wp[24 + i] = card;
 
54
            hashpile( 24 + i );
 
55
        }
 
56
        hashpile( deck );
 
57
#if PRINT
 
58
        print_layout();
 
59
#endif
 
60
        return;
 
61
    }
 
62
 
 
63
    card_t card = *Wp[from];
 
64
    Wlen[from]--;
 
65
    Wp[from]--;
 
66
    hashpile( from );
 
67
 
 
68
    /* Add to pile. */
 
69
 
 
70
    Wp[to]++;
 
71
    *Wp[to] = card;
 
72
    Wlen[to]++;
 
73
    hashpile( to );
 
74
 
 
75
    if ( m->turn_index == 1 )
 
76
    {
 
77
        card_t card2 = *Wp[deck];
 
78
        Wlen[deck]--;
 
79
        Wp[deck]--;
 
80
 
 
81
        hashpile(deck);
 
82
        /* Add to pile. */
 
83
 
 
84
        Wp[from]++;
 
85
        *Wp[from] = RANK( card2 ) + ( SUIT( card2 ) << 4 );
 
86
        Wlen[from]++;
 
87
    }
 
88
 
 
89
    hashpile(from);
 
90
#if PRINT
 
91
    print_layout();
 
92
#endif
 
93
}
 
94
 
 
95
void Mod3Solver::undo_move(MOVE *m)
 
96
{
 
97
#if PRINT2
 
98
    if ( m->totype == O_Type )
 
99
        fprintf( stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index );
 
100
    else
 
101
        fprintf( stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index );
 
102
    print_layout();
 
103
 
 
104
#endif
 
105
    int from, to;
 
106
    card_t card;
 
107
 
 
108
    from = m->from;
 
109
    to = m->to;
 
110
 
 
111
    if ( from == deck )
 
112
    {
 
113
        int len = m->card_index;
 
114
        if ( len > 8 )
 
115
            len = 8;
 
116
        for ( int i = len; i >= 0; i-- )
 
117
        {
 
118
            card_t card = *Wp[24+i];
 
119
            Wlen[deck]++;
 
120
            Wp[deck]++;
 
121
            *Wp[deck] = ( 1 << 7 ) + card;
 
122
 
 
123
            Wp[24 + i]--;
 
124
            Wlen[24 + i]--;
 
125
            hashpile( 24 + i );
 
126
        }
 
127
        hashpile( deck );
 
128
#if PRINT2
 
129
        print_layout();
 
130
#endif
 
131
        return;
 
132
    }
 
133
 
 
134
    if ( m->turn_index == 1)
 
135
    {
 
136
        card_t card = *Wp[from];
 
137
        Wp[deck]++;
 
138
        Wlen[deck]++;
 
139
        *Wp[deck] = ( 1 << 7 ) + card;
 
140
        Wlen[from]--;
 
141
        Wp[from]--;
 
142
 
 
143
        hashpile(deck);
 
144
    }
 
145
 
 
146
    card = *Wp[to];
 
147
    Wp[from]++;
 
148
    *Wp[from] = card;
 
149
    Wlen[from]++;
 
150
    *Wp[to]--;
 
151
    Wlen[to]--;
 
152
    hashpile(to);
 
153
    hashpile( from );
 
154
 
 
155
#if PRINT2
 
156
    print_layout();
 
157
#endif
 
158
}
 
159
 
 
160
/* Get the possible moves from a position, and store them in Possible[]. */
 
161
 
 
162
int Mod3Solver::get_possible_moves(int *a, int *numout)
 
163
{
 
164
    //print_layout();
 
165
 
 
166
    card_t card;
 
167
    MOVE *mp;
 
168
 
 
169
    *a = false;
 
170
    *numout = 0;
 
171
 
 
172
    int n = 0;
 
173
    mp = Possible;
 
174
 
 
175
    int first_empty_pile = -1;
 
176
    bool foundone = false;
 
177
 
 
178
    for (int i = 0; i < 32; ++i )
 
179
    {
 
180
        if ( !Wlen[i] )
 
181
            continue;
 
182
        card = *Wp[i];
 
183
 
 
184
        if ( RANK( card ) == PS_ACE )
 
185
        {
 
186
            mp->card_index = 0;
 
187
            mp->from = i;
 
188
            mp->to = aces;
 
189
            mp->totype = O_Type;
 
190
            mp->pri = 127;    /* unused */
 
191
            mp->turn_index = -1;
 
192
            if ( i >= 24 && Wlen[i] == 1 && Wlen[deck] )
 
193
                mp->turn_index = 1;
 
194
            n++;
 
195
            mp++;
 
196
            Possible[0] = mp[-1];
 
197
            *numout = 1;
 
198
            return 1;
 
199
        }
 
200
 
 
201
        for ( int j = 0; j < 32; ++j )
 
202
        {
 
203
            if ( i == j )
 
204
                continue;
 
205
 
 
206
            int current_row = i / 8;
 
207
            int row = j / 8;
 
208
 
 
209
            if ( Wlen[j] && RANK( *Wp[j] ) != row + 2 + ( Wlen[j] - 1 ) * 3 )
 
210
            {
 
211
                //fprintf( stderr, "rank %d %d\n", i, j );
 
212
                continue;
 
213
            }
 
214
 
 
215
            if ( row < 3 )
 
216
            {
 
217
                int min = ( card & PS_SUIT ) + row + 2;
 
218
                if ( Wlen[j] ) {
 
219
                    if ( RANK( *Wp[j] ) > 10 )
 
220
                        continue;
 
221
                    min = ( *Wp[j] & PS_SUIT ) + row + 2 + Wlen[j] * 3;
 
222
                }
 
223
                if ( min != card )
 
224
                    continue;
 
225
 
 
226
                // and now we figure if this makes sense at all
 
227
                if ( current_row == row )
 
228
                {
 
229
                    // if the only difference between i and j is the card,
 
230
                    // then it's not worth it
 
231
                    if ( Wlen[i] == Wlen[j] + 1 )
 
232
                        continue;
 
233
                }
 
234
                mp->pri = 12 + 20 * Wlen[j] - current_row * 2;
 
235
 
 
236
                mp->turn_index = -1;
 
237
                if ( i >= 24 && Wlen[i] == 1 && Wlen[deck] )
 
238
                    mp->turn_index = 1;
 
239
 
 
240
                if ( Wlen[j] > 0 && !foundone )
 
241
                {
 
242
                    foundone = true;
 
243
                    // we want to make sure we do not get useless moves
 
244
                    // if there are target moves
 
245
                    int index = 0;
 
246
                    while ( index < n )
 
247
                    {
 
248
                        if ( Possible[index].pri == 0 )
 
249
                        {
 
250
                            Possible[index] = Possible[n-1];
 
251
                            Possible[n-1] = *mp;
 
252
                            mp--;
 
253
                            n--;
 
254
                        } else
 
255
                            index++;
 
256
                    }
 
257
                }
 
258
 
 
259
            } else {
 
260
                if ( foundone )
 
261
                    continue;
 
262
 
 
263
                if ( Wlen[j] || ( Wlen[i] > 1 && current_row != 3 ) )
 
264
                    continue;
 
265
 
 
266
                if ( current_row == 3 && Wlen[i] == 1 )
 
267
                    continue;
 
268
 
 
269
                if ( RANK( card ) == current_row + 2 && current_row != 3 )
 
270
                    continue;
 
271
 
 
272
                if ( first_empty_pile != -1 && first_empty_pile != j )
 
273
                    continue;
 
274
 
 
275
                if ( first_empty_pile == -1 )
 
276
                    first_empty_pile = j;
 
277
 
 
278
                mp->pri = 0;
 
279
                mp->turn_index = -1;
 
280
            }
 
281
 
 
282
            mp->card_index = 0;
 
283
            mp->from = i;
 
284
            mp->to = j;
 
285
            mp->totype = W_Type;
 
286
            n++;
 
287
            mp++;
 
288
        }
 
289
    }
 
290
 
 
291
    if ( n == 0 && Wlen[deck] )
 
292
    {
 
293
        // move
 
294
        mp->card_index = 0;
 
295
        mp->from = deck;
 
296
        mp->to = 0;
 
297
        mp->totype = W_Type;
 
298
        mp->pri = 0;    /* unused */
 
299
        mp->turn_index = -1;
 
300
        mp->card_index = Wlen[deck];
 
301
        n++;
 
302
        mp++;
 
303
    }
 
304
 
 
305
    return n;
 
306
}
 
307
 
 
308
void Mod3Solver::unpack_cluster( int  )
 
309
{
 
310
}
 
311
 
 
312
bool Mod3Solver::isWon()
 
313
{
 
314
    return getOuts() == 52 * 2;
 
315
}
 
316
 
 
317
int Mod3Solver::getOuts()
 
318
{
 
319
    int ret = Wlen[aces];
 
320
    for ( int i = 0; i < 8 * 3; i++ )
 
321
        ret += Wlen[i];
 
322
    return ret;
 
323
}
 
324
 
 
325
Mod3Solver::Mod3Solver(const Mod3 *dealer)
 
326
    : Solver()
 
327
{
 
328
    // 24 targets, 8 playing fields, deck, aces
 
329
    setNumberPiles( 34 );
 
330
    deal = dealer;
 
331
}
 
332
 
 
333
/* Read a layout file.  Format is one pile per line, bottom to top (visible
 
334
card).  Temp cells and Out on the last two lines, if any. */
 
335
 
 
336
void Mod3Solver::translate_layout()
 
337
{
 
338
    /* Read the workspace. */
 
339
 
 
340
    int w = 0;
 
341
    int total = 0;
 
342
    for ( int row = 0; row < 4; ++row )
 
343
    {
 
344
        for ( int col = 0; col < 8; ++col )
 
345
        {
 
346
            int i = translate_pile(deal->stack[row][col], W[w], 52);
 
347
            Wp[w] = &W[w][i - 1];
 
348
            Wlen[w] = i;
 
349
            total += i;
 
350
            w++;
 
351
        }
 
352
    }
 
353
 
 
354
    aces = w;
 
355
    int i = translate_pile(deal->aces, W[w], 52);
 
356
    Wp[w] = &W[w][i-1];
 
357
    Wlen[w] = i;
 
358
 
 
359
    deck = ++w;
 
360
 
 
361
    i = translate_pile(Deck::deck(), W[w], 104);
 
362
    Wp[w] = &W[w][i-1];
 
363
    Wlen[w] = i;
 
364
}
 
365
 
 
366
int Mod3Solver::getClusterNumber()
 
367
{
 
368
    return 0;
 
369
}
 
370
 
 
371
MoveHint *Mod3Solver::translateMove( const MOVE & m )
 
372
{
 
373
    if ( m.from == deck )
 
374
        return 0;
 
375
 
 
376
    Pile *frompile = deal->stack[m.from / 8][m.from % 8];
 
377
    Card *card = frompile->top();
 
378
 
 
379
    if ( m.to == aces )
 
380
    {
 
381
        return new MoveHint( card, deal->aces, m.pri );
 
382
    } else {
 
383
        return new MoveHint( card, deal->stack[m.to / 8][m.to % 8], m.pri );
 
384
    }
 
385
}
 
386
 
 
387
void Mod3Solver::print_layout()
 
388
{
 
389
    int i, w = 0, o;
 
390
 
 
391
    fprintf(stderr, "print-layout-begin\n");
 
392
    for ( int row = 0; row < 3; ++row )
 
393
    {
 
394
        fprintf( stderr, "Row%d: ", row );
 
395
        for (int col = 0; col < 8; col++)
 
396
        {
 
397
            if ( Wlen[w] )
 
398
                printcard(*Wp[w], stderr);
 
399
            else
 
400
                fprintf( stderr, "   " );
 
401
            fprintf( stderr, "(%02d) ", w );
 
402
            w++;
 
403
        }
 
404
        fputc('\n', stderr);
 
405
    }
 
406
 
 
407
    for (int col = 0; col < 8; col++)
 
408
    {
 
409
        fprintf( stderr, "Play%02d: ", w );
 
410
        for (i = 0; i < Wlen[w]; i++) {
 
411
            printcard(W[w][i], stderr);
 
412
        }
 
413
        fputc('\n', stderr);
 
414
        w++;
 
415
    }
 
416
 
 
417
    fprintf( stderr, "Aces: " );
 
418
    for (o = 0; o < Wlen[aces]; o++) {
 
419
        printcard(W[aces][o], stderr);
 
420
    }
 
421
    fputc( '\n', stderr );
 
422
 
 
423
    fprintf( stderr, "Deck: " );
 
424
    for (o = 0; o < Wlen[deck]; o++) {
 
425
        printcard(W[deck][o], stderr);
 
426
    }
 
427
 
 
428
    fprintf(stderr, "\nprint-layout-end\n");
 
429
}