File: map_memory_test.cpp

package info (click to toggle)
cataclysm-dda 0.H-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 710,808 kB
  • sloc: cpp: 524,019; python: 11,580; sh: 1,228; makefile: 1,169; xml: 507; javascript: 150; sql: 56; exp: 41; perl: 37
file content (263 lines) | stat: -rw-r--r-- 10,313 bytes parent folder | download
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
#include <bitset>
#include <cstdio>
#include <sstream>
#include <type_traits>

#include "cata_catch.h"
#include "game_constants.h"
#include "json.h"
#include "lru_cache.h"
#include "map.h"
#include "map_memory.h"
#include "point.h"

static constexpr tripoint_abs_ms p1{ -SEEX - 2, -SEEY - 3, -1 };
static constexpr tripoint_abs_ms p2{ 5, 7, -1 };
static constexpr tripoint_abs_ms p3{ SEEX * 2 + 5, SEEY + 7, -1 };
static constexpr tripoint_abs_ms p4{ SEEX * 3 + 2, SEEY * 7 + 1, -1 };

TEST_CASE( "map_memory_keeps_region", "[map_memory]" )
{
    map_memory memory;
    CHECK( memory.prepare_region( p1, p2 ) );
    CHECK( !memory.prepare_region( p1, p2 ) );
    CHECK( !memory.prepare_region( p1 + tripoint_east, p2 + tripoint_east ) );
    CHECK( memory.prepare_region( p2, p3 ) );
    CHECK( memory.prepare_region( p1, p3 ) );
    CHECK( !memory.prepare_region( p1, p3 ) );
    CHECK( !memory.prepare_region( p2, p3 ) );
    CHECK( memory.prepare_region( p1, p4 ) );
    CHECK( !memory.prepare_region( p2, p3 ) );
    CHECK( memory.prepare_region(
               tripoint_abs_ms( p2.xy(), -p2.z() ),
               tripoint_abs_ms( p3.xy(), -p3.z() )
           ) );
}

TEST_CASE( "map_memory_defaults", "[map_memory]" )
{
    map_memory memory;
    memory.prepare_region( p1, p2 );
    CHECK( memory.get_tile( p1 ).symbol == 0 );
    memorized_tile default_tile = memory.get_tile( p1 );
    CHECK( default_tile.symbol == 0 );
    CHECK( default_tile.get_ter_id().empty() );
    CHECK( default_tile.get_ter_subtile() == 0 );
    CHECK( default_tile.get_ter_rotation() == 0 );
    CHECK( default_tile.get_dec_id().empty() );
    CHECK( default_tile.get_dec_subtile() == 0 );
    CHECK( default_tile.get_dec_rotation() == 0 );
}

TEST_CASE( "map_memory_remembers", "[map_memory]" )
{
    map_memory memory;
    memory.prepare_region( p1, p2 );
    memory.set_tile_symbol( p1, 1 );
    memory.set_tile_symbol( p2, 2 );
    CHECK( memory.get_tile( p1 ).symbol == 1 );
    CHECK( memory.get_tile( p2 ).symbol == 2 );

    const memorized_tile &mt = memory.get_tile( p2 );

    memory.set_tile_decoration( p2, "foo", 42, 3 );
    CHECK( mt.get_dec_id() == "foo" );
    CHECK( mt.get_dec_subtile() == 42 );
    CHECK( mt.get_dec_rotation() == 3 );
    CHECK( mt.get_ter_id().empty() );
    CHECK( mt.get_ter_subtile() == 0 );
    CHECK( mt.get_ter_rotation() == 0 );

    memory.set_tile_terrain( p2, "t_foo", 43, 2 );
    CHECK( mt.get_dec_id() == "foo" );
    CHECK( mt.get_dec_subtile() == 42 );
    CHECK( mt.get_dec_rotation() == 3 );
    CHECK( mt.get_ter_id() == "t_foo" );
    CHECK( mt.get_ter_subtile() == 43 );
    CHECK( mt.get_ter_rotation() == 2 );

    memory.set_tile_decoration( p2, "bar", 44, 1 );
    CHECK( mt.get_dec_id() == "bar" );
    CHECK( mt.get_dec_subtile() == 44 );
    CHECK( mt.get_dec_rotation() == 1 );
    CHECK( mt.get_ter_id() == "t_foo" );
    CHECK( mt.get_ter_subtile() == 43 );
    CHECK( mt.get_ter_rotation() == 2 );
}

TEST_CASE( "map_memory_overwrites", "[map_memory]" )
{
    map_memory memory;
    memory.prepare_region( p1, p2 );
    memory.set_tile_symbol( p1, 1 );
    memory.set_tile_symbol( p2, 2 );
    memory.set_tile_symbol( p2, 3 );
    CHECK( memory.get_tile( p1 ).symbol == 1 );
    CHECK( memory.get_tile( p2 ).symbol == 3 );
}

TEST_CASE( "map_memory_forgets", "[map_memory]" )
{
    map_memory memory;
    memory.prepare_region( p1, p2 );
    memory.set_tile_decoration( p1, "vp_foo", 42, 3 );
    memory.set_tile_terrain( p1, "t_foo", 43, 2 );
    const memorized_tile &mt = memory.get_tile( p1 );
    CHECK( mt.symbol == 0 );
    CHECK( mt.get_ter_id() == "t_foo" );
    CHECK( mt.get_ter_subtile() == 43 );
    CHECK( mt.get_ter_rotation() == 2 );
    CHECK( mt.get_dec_id() == "vp_foo" );
    CHECK( mt.get_dec_subtile() == 42 );
    CHECK( mt.get_dec_rotation() == 3 );
    memory.set_tile_symbol( p1, 1 );
    CHECK( mt.symbol == 1 );
    memory.clear_tile_decoration( p1, /* prefix = */ "vp_" );
    CHECK( mt.symbol == 0 );
    CHECK( mt.get_ter_id() == "t_foo" );
    CHECK( mt.get_ter_subtile() == 43 );
    CHECK( mt.get_ter_rotation() == 2 );
    CHECK( mt.get_dec_id().empty() );
    CHECK( mt.get_dec_subtile() == 0 );
    CHECK( mt.get_dec_rotation() == 0 );
}

// TODO: map memory save / load

#include <chrono>

TEST_CASE( "lru_cache_perf", "[.]" )
{
    constexpr int max_size = 1000000;
    lru_cache<tripoint, int> symbol_cache;
    const std::chrono::high_resolution_clock::time_point start1 =
        std::chrono::high_resolution_clock::now();
    for( int i = 0; i < 1000000; ++i ) {
        for( int j = -60; j <= 60; ++j ) {
            symbol_cache.insert( max_size, { i, j, 0 }, 1 );
        }
    }
    const std::chrono::high_resolution_clock::time_point end1 =
        std::chrono::high_resolution_clock::now();
    const long long diff1 = std::chrono::duration_cast<std::chrono::microseconds>
                            ( end1 - start1 ).count();
    printf( "completed %d insertions in %lld microseconds.\n", max_size, diff1 );
    /*
     * Original tripoint hash    completed 1000000 insertions in 96136925 microseconds.
     * Table based interleave v1 completed 1000000 insertions in 41435604 microseconds.
     * Table based interleave v2 completed 1000000 insertions in 40856530 microseconds.
     * Jbtw hash                 completed 1000000 insertions in 19049163 microseconds.
     *                                                     rerun 21152804
     * With 1024 batch           completed 1000000 insertions in 39902325 microseconds.
     * backed out batching       completed 1000000 insertions in 20332498 microseconds.
     * rerun                     completed 1000000 insertions in 21659107 microseconds.
     * simple batching, disabled completed 1000000 insertions in 18541486 microseconds.
     * simple batching, 1024     completed 1000000 insertions in 23102395 microseconds.
     * rerun                     completed 1000000 insertions in 31337290 microseconds.
     */
}

// There are 4 quadrants we want to check,
// 1 | 2
// -----
// 3 | 4
// The partitions are defined by partition.x and partition.y
// Each partition has an expected value, and should be homogenous.
static void check_quadrants( std::bitset<MAPSIZE *SEEX *MAPSIZE *SEEY> &test_cache,
                             const point &partition,
                             bool first_val, bool second_val, bool third_val, bool fourth_val )
{
    int y = 0;
    for( ; y < partition.y; ++y ) {
        size_t y_offset = y * SEEX * MAPSIZE;
        int x = 0;
        for( ; x < partition.x; ++x ) {
            INFO( x << " " << y );
            CHECK( first_val == test_cache[ y_offset + x ] );
        }
        for( ; x < SEEX * MAPSIZE; ++x ) {
            INFO( x << " " << y );
            CHECK( second_val == test_cache[ y_offset + x ] );
        }
    }
    for( ; y < SEEY * MAPSIZE; ++y ) {
        size_t y_offset = y * SEEX * MAPSIZE;
        int x = 0;
        for( ; x < partition.x; ++x ) {
            INFO( x << " " << y );
            CHECK( third_val == test_cache[ y_offset + x ] );
        }
        for( ; x < SEEX * MAPSIZE; ++x ) {
            INFO( x << " " << y );
            CHECK( fourth_val == test_cache[ y_offset + x ] );
        }
    }
}

static constexpr size_t first_twelve = SEEX;
static constexpr size_t last_twelve = ( SEEX *MAPSIZE ) - SEEX;

TEST_CASE( "shift_map_memory_bitset_cache" )
{
    std::bitset<MAPSIZE *SEEX *MAPSIZE *SEEY> test_cache;

    GIVEN( "all bits are set" ) {
        test_cache.set();
        WHEN( "positive x shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_east );
            THEN( "last 12 columns are 0, rest are 1" ) {
                check_quadrants( test_cache, point( last_twelve, 0 ),
                                 true, false, true, false );
            }
        }
        WHEN( "negative x shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_west );
            THEN( "first 12 columns are 0, rest are 1" ) {
                check_quadrants( test_cache, point( first_twelve, 0 ),
                                 false, true, false, true );
            }
        }
        WHEN( "positive y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_south );
            THEN( "last 12 rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( 0, last_twelve ),
                                 true, true, false, false );
            }
        }
        WHEN( "negative y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_north );
            THEN( "first 12 rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( 0, first_twelve ),
                                 false, false, true, true );
            }
        }
        WHEN( "positive x, positive y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_south_east );
            THEN( "last 12 columns and rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( last_twelve, last_twelve ),
                                 true, false, false, false );
            }
        }
        WHEN( "positive x, negative y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_north_east );
            THEN( "last 12 columns and first 12 rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( last_twelve, first_twelve ),
                                 false, false, true, false );
            }
        }
        WHEN( "negative x, positive y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_south_west );
            THEN( "first 12 columns and last 12 rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( first_twelve, last_twelve ),
                                 false, true, false, false );
            }
        }
        WHEN( "negative x, negative y shift" ) {
            shift_bitset_cache<MAPSIZE_X, SEEX>( test_cache, point_north_west );
            THEN( "first 12 columns and rows are 0, rest are 1" ) {
                check_quadrants( test_cache, point( first_twelve, first_twelve ),
                                 false, false, false, true );
            }
        }
    }
}