etc
Check-in [821ccd6221]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add test bed for Pack class Also, add even more SDL_Delay before SDL_Quit because its timer thread is (apparently, out of pure observation) not joined and bad things happen.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:821ccd6221c4279ce99a36718cc31dde245496bc
User & Date: alzwded 2014-04-12 11:30:21
Context
2014-04-12
11:42
moved test related macros to test.hxx check-in: 5326ee38a0 user: alzwded tags: trunk
11:30
Add test bed for Pack class Also, add even more SDL_Delay before SDL_Quit because its timer thread is (apparently, out of pure observation) not joined and bad things happen. check-in: 821ccd6221 user: alzwded tags: trunk
10:14
update README.md check-in: 397df2bf59 user: alzwded tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to t2048/2048.cpp.

3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <cstdarg>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cstring>
#include <ctime>
#include "header.h"


#define ONLY_IF_TALKING // debug stuff
static bool TALKATIVE = 0;
#define TALK if(TALKATIVE) printf

cell_t board[16] = {
    1, 0, 1, 2,
    1, 1, 1, 0,
    0, 0, 1, 0,
    2, 1, 0, 1
};

// resolves movement on cells
class Pack {
    // pointers to the actual cells that will be modified
    std::deque<cell_t*> pointers_;

    // perform actual shift removing any 0 values (empty cells)
    void shift_(std::list<cell_t>& cells, int& moved)
    {
        moved = 0;
        TALK("new shift\n");
        // copy values into results vector
        std::transform(
                pointers_.rbegin(),
                pointers_.rend(),
                std::inserter(cells, cells.begin()),
                [&](cell_t* p) { return *p; });

        ONLY_IF_TALKING for(auto i = cells.begin(); i != cells.end(); ++i) {
            TALK("%d ", *i);
        ONLY_IF_TALKING }
        TALK("\n");

        for(auto cell = cells.begin(), next = cell;
                cell != cells.end() && ++next != cells.end();
                next = cell)
        {
            TALK("I am %d\n", *cell);
            ONLY_IF_TALKING for(auto cell = cells.begin(); cell != cells.end(); ++cell) {
                TALK("%d ", *cell);
            ONLY_IF_TALKING }
            TALK("\n");
            if(!*cell) { // special case I don't know how to get rid of: 0 on edge
                TALK("removing self (0)\n");
                cells.erase(cell);
                cell = next;
                if(next != cells.end() && *next) moved = 1;
            } else if(!*next) { // eliminate empty cells
                TALK("removing buddy (0)\n");
                cells.erase(next);
                next = cell;
                next++;
                if(next != cells.end() && *next) moved = 1;
            } else if(*cell == *(next)) { // merge cells of equal value
                moved = 1;
                TALK("merging with buddy (%d)\n", *cell);
                ++*cell;
                cells.erase(next);
                ++cell;
            } else { // default, move to next cell
                TALK("moving along\n");
                ++cell;
            }
        }
    }

    struct Translator {
        std::list<cell_t> const& cells_;
        std::list<cell_t>::const_iterator i_;
        Translator(std::list<cell_t> const& cells)
            : cells_(cells)
            , i_(cells.begin())
        {}

        void operator()(cell_t* cell)
        {
            if(i_ != cells_.end()) *cell = *i_++;
            else *cell = 0;
        }
    };

public:
    typedef std::deque<cell_t*> Builder;

    Pack(cell_t* first, ...)
    {
        va_list p;
        va_start(p, first);
        for(cell_t* i = first; i; i = va_arg(p, cell_t*)) {
            TALK("pushing %d\n", *i);
            pointers_.push_back(i);
        }
        va_end(p);
    }

    Pack(Builder const& bld)
    {
        std::copy(bld.begin(), bld.end(), std::inserter(pointers_, pointers_.begin()));
    }

    // shift cells left-to-right relative to the order the cells were
    //     passed into the constructor
    int shift()
    {
        std::list<cell_t> cells;
        int anythingAccomplished = 0;
        shift_(cells, anythingAccomplished);
        std::for_each(pointers_.rbegin(), pointers_.rend(), Translator(cells));
        return anythingAccomplished;
    }
};

// a line is defined as A*i + B*j + B0, for j = 0..3 and a given i
template<int A, int B0, int B>
int tshift()
{
    int ret = 0;
    for(size_t i = 0; i < 4; ++i) {
        Pack::Builder line;







>

<
<
<
<







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3
4
5
6
7
8
9
10
11




12
13
14
15
16
17
18





































































































19
20
21
22
23
24
25
#include <cstdarg>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cstring>
#include <ctime>
#include "header.h"
#include "pack.hxx"





cell_t board[16] = {
    1, 0, 1, 2,
    1, 1, 1, 0,
    0, 0, 1, 0,
    2, 1, 0, 1
};






































































































// a line is defined as A*i + B*j + B0, for j = 0..3 and a given i
template<int A, int B0, int B>
int tshift()
{
    int ret = 0;
    for(size_t i = 0; i < 4; ++i) {
        Pack::Builder line;

Changes to t2048/Makefile.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15



16
17
18
19
20
21
22
23
24



25
26




27
28
29
all: a.out 2048-cleaned.cpp

a.out: 2048.o display.o
	g++ -g 2048.o display.o -lSDL -lSDL_ttf

2048.exe: 2048.obj display.obj 
	i686-w64-mingw32-g++ -static-libgcc -static-libstdc++ -o 2048.exe 2048.obj display.obj -Lvendor/SDL-1.2.15/bin -Lvendor/SDL_ttf-2.0.11/lib/x86 -lSDL -lSDL_ttf
	cp vendor/SDL-1.2.15/bin/SDL.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/SDL_ttf.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/libfreetype-6.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/zlib1.dll .

2048.obj: 2048.cpp
	i686-w64-mingw32-g++ --std=gnu++0x -g -o 2048.obj -c 2048.cpp




display.obj: display.c
	i686-w64-mingw32-gcc --std=gnu99 -g -c -o display.obj -g --std=gnu99 -c -Ivendor/include display.c

display.o: display.c
	gcc -g --std=gnu99 -c display.c

2048.o: 2048.cpp
	g++ -g --std=gnu++11 -c 2048.cpp -o 2048.o




2048-cleaned.cpp: 2048.cpp
	sed 2048.cpp -e '/TALK/d' > 2048-cleaned.cpp





clean:
	rm -f a.out 2048-cleaned.cpp *.o 2048.exe *.obj *.dll


|
|

|
|








>
>
>









>
>
>


>
>
>
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
all: a.out 2048-cleaned.cpp

a.out: 2048.o display.o pack.o
	g++ -g 2048.o pack.o display.o -lSDL -lSDL_ttf

2048.exe: 2048.obj display.obj pack.obj
	i686-w64-mingw32-g++ -static-libgcc -static-libstdc++ -o 2048.exe 2048.obj pack.obj display.obj -Lvendor/SDL-1.2.15/bin -Lvendor/SDL_ttf-2.0.11/lib/x86 -lSDL -lSDL_ttf
	cp vendor/SDL-1.2.15/bin/SDL.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/SDL_ttf.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/libfreetype-6.dll .
	cp vendor/SDL_ttf-2.0.11/lib/x86/zlib1.dll .

2048.obj: 2048.cpp
	i686-w64-mingw32-g++ --std=gnu++0x -g -o 2048.obj -c 2048.cpp

pack.obj: pack.cpp
	i686-w64-mingw32-g++ --std=gnu++0x -g -o pack.obj -c pack.cpp

display.obj: display.c
	i686-w64-mingw32-gcc --std=gnu99 -g -c -o display.obj -g --std=gnu99 -c -Ivendor/include display.c

display.o: display.c
	gcc -g --std=gnu99 -c display.c

2048.o: 2048.cpp
	g++ -g --std=gnu++11 -c 2048.cpp -o 2048.o

pack.o: pack.cpp
	g++ -g --std=gnu++11 -c pack.cpp -o pack.o

2048-cleaned.cpp: 2048.cpp
	sed 2048.cpp -e '/TALK/d' > 2048-cleaned.cpp

test.out: pack.cpp
	g++ -g --std=gnu++11 -DTEST_PACK -o test.out pack.cpp
	./run-tests.csh

clean:
	rm -f a.out 2048-cleaned.cpp *.o 2048.exe *.obj *.dll

Changes to t2048/display.c.

117
118
119
120
121
122
123
124
125
126
127
128
                }
                break;
            }
        }
    }

    SDL_SetTimer(0, NULL);
    SDL_Delay(20); // why? :'(
    SDL_FreeSurface(window);
    TTF_Quit();
    SDL_Quit();
}







|




117
118
119
120
121
122
123
124
125
126
127
128
                }
                break;
            }
        }
    }

    SDL_SetTimer(0, NULL);
    SDL_Delay(100); // HOW MUCH TIME DO YOU NEED?!?!?! //SDL_Delay(20); // why? :'(
    SDL_FreeSurface(window);
    TTF_Quit();
    SDL_Quit();
}

Added t2048/pack.cpp.

























































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
#include "pack.hxx"
#include "header.h"
#include <cstdio>
#include <algorithm>
#include <deque>
#include <list>
#include <cstdarg>

namespace { // internal
struct Translator {
    std::list<cell_t> const& cells_;
    std::list<cell_t>::const_iterator i_;
    Translator(std::list<cell_t> const& cells)
        : cells_(cells)
        , i_(cells.begin())
    {}

    void operator()(cell_t* cell)
    {
        if(i_ != cells_.end()) *cell = *i_++;
        else *cell = 0;
    }
};
} // namespace

// perform actual shift removing any 0 values (empty cells)
static void shift_(std::list<cell_t>& cells, int& moved)
{
    moved = 0;


    for(auto cell = cells.begin(), next = cell;
            cell != cells.end() && ++next != cells.end();
            next = cell)
    {
        if(!*cell) { // special case I don't know how to get rid of: 0 on edge
            cells.erase(cell);
            cell = next;
            if(next != cells.end() && *next) moved = 1;
        } else if(!*next) { // eliminate empty cells
            cells.erase(next);
            next = cell;
            next++;
            if(next != cells.end() && *next) moved = 1;
        } else if(*cell == *(next)) { // merge cells of equal value
            moved = 1;
            ++*cell;
            cells.erase(next);
            ++cell;
        } else { // default, move to next cell
            ++cell;
        }
    }
}

Pack::Pack(cell_t* first, ...)
{
    va_list p;
    va_start(p, first);
    for(cell_t* i = first; i; i = va_arg(p, cell_t*)) {
        pointers_.push_back(i);
    }
    va_end(p);
}

Pack::Pack(Builder const& bld)
{
    std::copy(bld.begin(), bld.end(), std::inserter(pointers_, pointers_.begin()));
}

// shift cells left-to-right relative to the order the cells were
//     passed into the constructor
int Pack::shift()
{
    std::list<cell_t> cells;
    int anythingAccomplished = 0;
    // copy values into results vector
    std::transform(
            pointers_.rbegin(),
            pointers_.rend(),
            std::inserter(cells, cells.begin()),
            [&](cell_t* p) { return *p; });
    shift_(cells, anythingAccomplished);
    std::for_each(pointers_.rbegin(), pointers_.rend(), Translator(cells));
    return anythingAccomplished;
}

#define TEST_BEGIN(NAME) \
{ #NAME, [&]() { \
    /*clock_t t0 = clock();*/ \
    printf("%s: ", #NAME);

#define TEST_END(NAME) \
    printf("OK\n"); \
    /*printf("%s: test took %5.3fus to run\n", #NAME, (float)(clock() - t0)/1000.f/CLOCKS_PER_SEC);*/ \
    return 0; \
               }},

#ifdef TEST_PACK
# include <cassert>
# include <cstring>
//# include <ctime>

# define NELEMENTS(A) ( sizeof(A) / sizeof(A[0]) )

static struct {
    const char* name;
    int (*fn)();
} tests[] = {
    TEST_BEGIN(EmptyCellIsRemoved) {
        std::list<cell_t> line;
        line.push_back(0);
        line.push_back(0);
        std::list<cell_t> ref;
        ref.push_back(0); // particularity of the implementation, a value already on the edge is left as is since it would not affect the board results in any way (which pads with 0s anyway)
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(EmptyCellIsRemoved)
    TEST_BEGIN(ValueCellEatsEmptyCell) {
        std::list<cell_t> line;
        line.push_back(0);
        line.push_back(1);
        std::list<cell_t> ref;
        ref.push_back(1);
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(ValueCellEatsEmptyCell)
    TEST_BEGIN(EmptyCellEatenByValueCell) {
        std::list<cell_t> line;
        line.push_back(1);
        line.push_back(0);
        std::list<cell_t> ref;
        ref.push_back(1);
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(EmptyCellEatenByValueCell)
    TEST_BEGIN(EqualCellsAreMerged) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue);
        std::list<cell_t> ref;
        ref.push_back(randomValue + 1);
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(EqualCellsAreMerged)
    TEST_BEGIN(NonEqualCellsAreNotMerged) {
        cell_t randomValue1 = 42;
        cell_t randomValue2 = 3;
        std::list<cell_t> line;
        line.push_back(randomValue1);
        line.push_back(randomValue2);
        std::list<cell_t> ref;
        ref.push_back(randomValue1);
        ref.push_back(randomValue2);
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(NonEqualCellsAreNotMerged)
    TEST_BEGIN(OnlyRightMostCellsAreMerged) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue);
        line.push_back(randomValue);
        std::list<cell_t> ref;
        ref.push_back(randomValue + 1);
        ref.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(line == ref);
    } TEST_END(OnlyRightMostCellsAreMerged)

    TEST_BEGIN(OnlyEmptyCellsDoesntCountAsAMove) {
        std::list<cell_t> line;
        line.push_back(0);
        line.push_back(0);
        int moved(0);
        shift_(line, moved);
        assert(!moved);
    } TEST_END(OnlyEmptyCellsDoesntCountAsAMove)
    TEST_BEGIN(ValueCellEatsEmptyCellCountsAsAMove) {
        cell_t randomValue = 42;
        cell_t randomValue2 = 3;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(0);
        line.push_back(randomValue2);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(ValueCellEatsEmptyCellCountsAsAMove)
    TEST_BEGIN(MergingCellsCountsAsAMove) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(MergingCellsCountsAsAMove)
    TEST_BEGIN(NotMergingCellsDoesntCountAsAMove) {
        cell_t randomValue = 42;
        cell_t randomValue2 = 3;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue2);
        int moved(0);
        shift_(line, moved);
        assert(!moved);
    } TEST_END(NotMergingCellsDoesntCountAsAMove)
    TEST_BEGIN(EmptyCellAtTipDoesntCountAsAMove) {
        cell_t randomValue = 42;
        cell_t randomValue2 = 3;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue2);
        line.push_back(0);
        int moved(0);
        shift_(line, moved);
        assert(!moved);
    } TEST_END(EmptyCellAtTipDoesntCountAsAMove)
    TEST_BEGIN(IOfZeroBeingEatenByValueCellCountsAsAMove) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(0);
        line.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(IOfZeroBeingEatenByValueCellCountsAsAMove)

    TEST_BEGIN(EatingACellDoesNotMergeNewNeighbours) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(randomValue);
        line.push_back(randomValue + 1);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(EatingACellDoesNotMergeNewNeighbours)
    TEST_BEGIN(EatingACellDoesNotMergeNewNeighboursRevisited) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue + 1);
        line.push_back(randomValue);
        line.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(EatingACellDoesNotMergeNewNeighbours)
    TEST_BEGIN(EatingACellDoesNotMergeNewNeighboursReRevisited) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue);
        line.push_back(0);
        line.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(EatingACellDoesNotMergeNewNeighbours)
    TEST_BEGIN(EatingACellDoesNotMergeNewNeighboursReReRevisited) {
        cell_t randomValue = 42;
        std::list<cell_t> line;
        line.push_back(randomValue + 1);
        line.push_back(0);
        line.push_back(randomValue);
        line.push_back(randomValue);
        int moved(0);
        shift_(line, moved);
        assert(moved);
    } TEST_END(EatingACellDoesNotMergeNewNeighbours)
};

int main(int argc, char* argv[])
{
    size_t i = 0;
    assert(argc == 2);
    if(argv[1][0] == '-' && argv[1][1] == 'l') {
        for(; i < NELEMENTS(tests); ++i) {
            printf("%s ", tests[i].name);
        }
        printf("\n");
        return 0;
    }
    for(; i < NELEMENTS(tests); ++i) {
        if(strcmp(argv[1], tests[i].name) == 0) {
            return tests[i].fn();
        }
    }
# define NO_TEST_FOUND false
    assert(NO_TEST_FOUND);
    return 255;
}
#endif

Added t2048/pack.hxx.



















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef PACK_HXX
#define PACK_HXX

#include "header.h"
#include <deque>
#include <cstdarg>

// resolves movement on cells
class Pack {
    // pointers to the actual cells that will be modified
    std::deque<cell_t*> pointers_;

public:
    typedef std::deque<cell_t*> Builder;

    Pack(cell_t* first, ...);

    Pack(Builder const& bld);

    // shift cells left-to-right relative to the order the cells were
    //     passed into the constructor
    int shift();
};

#endif

Added t2048/run-tests.csh.















>
>
>
>
>
>
>
1
2
3
4
5
6
7
#!/bin/csh

set tests=`./test.out -l`

foreach test ($tests)
    ./test.out $test || echo "FAIL"
end