Censor the p-word
[anarch.git] / main_test.c
blobbb97a7bef312f2b49ec992d16caf40d74384b95e
1 /**
2 @file main_test.c
4 This is a front end that serves as a basic automatic test of the game. At this
5 point it's very simple and basically just checks if anything really
6 substantial wasn't broken.
8 This fronted tries to play the game and see if it behaves how expected. If you
9 change anything substantial in the game, this test may start to fail and you
10 may need to adjust it.
12 by Miloslav Ciz (drummyfish), 2019
14 Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
15 plus a waiver of all other intellectual property. The goal of this work is
16 be and remain completely in the public domain forever, available for any use
17 whatsoever.
20 #include <stdio.h>
21 #include <time.h>
23 #define SFG_SCREEN_RESOLUTION_X 67
24 #define SFG_SCREEN_RESOLUTION_Y 31
25 #define SFG_BACKGROUND_BLUR 1
26 #define SFG_DITHERED_SHADOW 1
27 #define SFG_FPS 30
29 #include "game.h"
30 #include "sounds.h"
32 uint8_t screen[SFG_SCREEN_RESOLUTION_X * SFG_SCREEN_RESOLUTION_Y];
33 uint8_t keys[SFG_KEY_COUNT];
35 uint32_t gameTime = 0;
37 int8_t SFG_keyPressed(uint8_t key)
39 return keys[key];
42 void SFG_getMouseOffset(int16_t *x, int16_t *y)
46 uint32_t SFG_getTimeMs()
48 return gameTime;
51 void SFG_sleepMs(uint16_t gameTimeMs)
55 int aaa = 100;
57 static inline void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex)
59 screen[y * SFG_SCREEN_RESOLUTION_X + x] = colorIndex;
62 void SFG_playSound(uint8_t soundIndex, uint8_t volume)
66 void SFG_setMusic(uint8_t value)
70 void SFG_processEvent(uint8_t event, uint8_t data)
74 void SFG_save(uint8_t data[SFG_SAVE_SIZE])
78 uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE])
80 return 0;
83 void printTestHeading(const char *text)
85 printf("\n~~~~~ testing: %s ~~~~~\n\n",text);
88 const char colors[8] = " .,-;imX";
90 void printScreen()
92 const char *c = screen;
94 for (uint8_t y = 0; y < SFG_SCREEN_RESOLUTION_Y; ++y)
96 for (uint8_t x = 0; x < SFG_SCREEN_RESOLUTION_X; ++x)
98 putchar(*c != 7 ? colors[(*c) % 8] : '@');
99 ++c;
102 putchar('\n');
106 int main(void)
108 puts("===== TESTING ANARCH =====\n");
110 puts("initializing");
112 #define ASSERT(text,cond) { printf("checking \"%s\": ",text); if (cond) puts("OK"); else { puts("ERROR"); return 1; }}
114 SFG_init();
116 double msPerFrame = 0;
118 ASSERT("frame == 0",SFG_game.frame == 0);
121 printTestHeading("music and sounds");
123 static const uint8_t expectedSamples[] = { 1, 0, 0, 0, 0, 0, 255, 251, 80, 240, 240, 10, 0, 6, 4, 0 };
125 uint16_t pos = 0;
127 for (uint32_t i = 0; i < (SFG_TRACK_COUNT * SFG_TRACK_SAMPLES); ++i)
129 uint8_t sample = SFG_getNextMusicSample();
131 if (i % 200000 == 0)
133 ASSERT("music sample", sample == expectedSamples[pos]);
134 pos++;
138 ASSERT("sfx sample",SFG_GET_SFX_SAMPLE(0,0) == 128);
139 ASSERT("sfx sample",SFG_GET_SFX_SAMPLE(1,200) == 112);
140 ASSERT("sfx sample",SFG_GET_SFX_SAMPLE(3,512) == 112);
141 ASSERT("sfx sample",SFG_GET_SFX_SAMPLE(4,1000) == 128);
145 printTestHeading("levels");
147 SFG_TileDefinition t;
148 uint8_t p;
150 t = SFG_getMapTile(&SFG_level1,10,8,&p);
151 ASSERT("level1 tile",SFG_TILE_FLOOR_HEIGHT(t) == 14 && SFG_TILE_CEILING_HEIGHT(t) == 0 && SFG_TILE_FLOOR_TEXTURE(t) == 4 && p == 0);
153 t = SFG_getMapTile(&SFG_level3,9,20,&p);
154 ASSERT("level3 tile",SFG_TILE_FLOOR_HEIGHT(t) == 17 && SFG_TILE_CEILING_HEIGHT(t) == 13 && SFG_TILE_FLOOR_TEXTURE(t) == 0 && p == 128);
156 t = SFG_getMapTile(&SFG_level5,-9,0,&p);
157 ASSERT("outside tile",SFG_TILE_FLOOR_HEIGHT(t) == 31 && SFG_TILE_CEILING_HEIGHT(t) == 0 && SFG_TILE_FLOOR_TEXTURE(t) == 7 && p == 0);
161 printTestHeading("gameplay");
163 for (uint8_t i = 0; i < SFG_KEY_COUNT; ++i)
164 keys[i] = 0;
166 #define STEP(ms) { printf("(fr %d, step %d ms) ",SFG_game.frame,ms); gameTime += ms; SFG_mainLoopBody(); }
167 #define PRESS(k) { printf("(press %d) ",k); keys[k] = 1; }
168 #define RELEASE(k) { printf("(release %d) ",k); keys[k] = 0; }
169 #define TEST_PIXEL(x,y,v) { printf("(testing pixel %d %d)",x,y); uint8_t val = screen[y * SFG_SCREEN_RESOLUTION_X + y]; if (val != v) { printf("\nERROR: expcted %d, got %d\n",v,val); return 1; }}
171 STEP(10)
172 STEP(100)
173 PRESS(SFG_KEY_DOWN) // select "exit"
174 STEP(1000)
175 RELEASE(SFG_KEY_DOWN)
176 TEST_PIXEL(10,20,64)
178 putchar('\n');
179 ASSERT("menu item == exit",SFG_getMenuItem(SFG_game.selectedMenuItem) == SFG_MENU_ITEM_EXIT)
181 PRESS(SFG_KEY_UP) // select "play"
182 STEP(700)
183 RELEASE(SFG_KEY_UP)
184 PRESS(SFG_KEY_A) // confirm "play"
185 STEP(100)
186 TEST_PIXEL(30,21,0)
187 RELEASE(SFG_KEY_A)
188 STEP(100)
189 PRESS(SFG_KEY_A) // skip intro
190 STEP(2000)
192 putchar('\n');
193 ASSERT("state == playing",SFG_game.state == SFG_GAME_STATE_PLAYING)
195 RELEASE(SFG_KEY_A)
196 PRESS(SFG_KEY_RIGHT) // turn
197 STEP(400)
198 RELEASE(SFG_KEY_RIGHT)
199 PRESS(SFG_KEY_UP) // take ammo
200 STEP(400)
202 putchar('\n');
203 ASSERT("weapon == shotgun",SFG_player.weapon == SFG_WEAPON_SHOTGUN)
205 RELEASE(SFG_KEY_UP)
206 PRESS(SFG_KEY_LEFT) // turn back
207 STEP(700)
208 RELEASE(SFG_KEY_LEFT)
209 PRESS(SFG_KEY_UP) // go to barrels
210 STEP(1000)
211 RELEASE(SFG_KEY_UP)
212 PRESS(SFG_KEY_RIGHT)
213 STEP(200)
214 RELEASE(SFG_KEY_RIGHT)
215 PRESS(SFG_KEY_A) // shoot barrels
216 STEP(700)
217 RELEASE(SFG_KEY_A)
219 putchar('\n');
220 ASSERT("health < 100",SFG_player.health < 100)
222 PRESS(SFG_KEY_UP)
223 STEP(720)
224 RELEASE(SFG_KEY_UP)
225 PRESS(SFG_KEY_LEFT)
226 STEP(300)
227 RELEASE(SFG_KEY_LEFT)
228 PRESS(SFG_KEY_UP)
229 STEP(700)
230 RELEASE(SFG_KEY_UP)
231 PRESS(SFG_KEY_RIGHT)
232 STEP(700)
233 RELEASE(SFG_KEY_RIGHT)
234 PRESS(SFG_KEY_UP)
235 STEP(850)
236 RELEASE(SFG_KEY_UP)
237 STEP(2500)
238 PRESS(SFG_KEY_A) // shoot monster
239 STEP(200)
240 RELEASE(SFG_KEY_A) // shoot monster
241 STEP(900)
242 PRESS(SFG_KEY_LEFT)
243 PRESS(SFG_KEY_NEXT_WEAPON) // switch to machine gun
244 STEP(100)
245 RELEASE(SFG_KEY_LEFT)
246 RELEASE(SFG_KEY_NEXT_WEAPON)
248 putchar('\n');
249 ASSERT("weapon == machine gun",SFG_player.weapon == SFG_WEAPON_MACHINE_GUN)
251 STEP(1000)
252 PRESS(SFG_KEY_A) // shoot
253 STEP(2000)
255 putchar('\n');
256 ASSERT("health == 74",SFG_player.health == 74)
258 RELEASE(SFG_KEY_A)
260 STEP(100)
261 PRESS(SFG_KEY_LEFT)
263 #define FRAMES 1000000
265 printf("\nbenchmarking frame time on %d frames.\n",FRAMES);
267 clock_t t1, t2;
269 t1 = clock();
270 STEP(FRAMES);
271 t2 = clock();
272 msPerFrame = (((double) (t2 - t1)) * 1000.0) / (CLOCKS_PER_SEC * FRAMES);
273 RELEASE(SFG_KEY_LEFT)
274 STEP(100)
276 PRESS(SFG_KEY_C) // open menu
277 PRESS(SFG_KEY_DOWN)
278 STEP(200)
279 RELEASE(SFG_KEY_C)
281 putchar('\n');
282 ASSERT("state == menu",SFG_game.state == SFG_GAME_STATE_MENU)
284 STEP(1000)
285 PRESS(SFG_KEY_A) // exit game
286 STEP(100)
288 putchar('\n');
289 ASSERT("game exitted",SFG_mainLoopBody() == 0)
291 putchar('\n');
292 printScreen();
294 #undef PRESS
295 #undef RELEASE
296 #undef STEP
299 puts("======================================\n\nDone.\nEverything seems OK.");
301 printf("benchmarked ms per frame: %lf\n",msPerFrame);
303 return 0;