ui gpu clipping
[fishladder.git] / fishladder_resources.h
1 // TEXTURES
2 // ===========================================================================================================
3
4 vg_tex2d tex_tile_data = { .path = "textures/tileset.qoi" };
5 vg_tex2d tex_tile_detail = { .path = "textures/tile_overlays.qoi" };
6 vg_tex2d tex_wood = { .path = "textures/wood.qoi" };
7 vg_tex2d tex_background = { .path = "textures/background.qoi" };
8 vg_tex2d tex_ball_noise = { .path = "textures/bnoise.qoi" };
9 vg_tex2d tex_monofur = { .path = "textures/ascii.qoi", .flags = VG_TEXTURE_NO_MIP };
10
11 vg_tex2d *texture_list[] = { &tex_tile_detail, &tex_tile_data, &tex_wood, &tex_background, &tex_ball_noise, &tex_monofur };
12
13 // AUDIO
14 // ===========================================================================================================
15
16 sfx_vol_control audio_volume_sfx = { .val = 1.0f, .name = "Sound effects" };
17 sfx_vol_control audio_volume_music = { .val = 1.0f, .name = "Music" };
18
19 sfx_system audio_system_sfx =
20 {
21 .vol = 1.f,
22 .ch = 1,
23 .vol_src = &audio_volume_sfx,
24 .name = "sfx"
25 };
26
27 sfx_set audio_tile_mod =
28 {
29 .sources = "\
30 sound/mod_01.ogg\0\
31 sound/mod_02.ogg\0\
32 sound/mod_03.ogg\0\
33 sound/mod_04.ogg\0\
34 sound/mod_05.ogg\0\
35 sound/mod_06.ogg\0",
36 .flags = 0
37 };
38
39 sfx_set audio_splitter =
40 {
41 .sources = "\
42 sound/splitter_01.ogg\0"
43 };
44
45 sfx_set audio_rolls =
46 {
47 .sources = "\
48 sound/rolling_01.ogg\0\
49 sound/rolling_02.ogg\0"
50 };
51
52 sfx_set audio_random =
53 {
54 .sources = "\
55 sound/random_01.ogg\0\
56 sound/random_02.ogg\0\
57 sound/random_03.ogg\0\
58 sound/random_04.ogg\0\
59 sound/random_05.ogg\0\
60 sound/random_06.ogg\0\
61 sound/random_07.ogg\0\
62 sound/random_08.ogg\0"
63 };
64
65 // One two or three layers of rolling noise
66 sfx_system audio_system_balls_rolling =
67 {
68 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
69 .name = "Balls Rolling", .flags = SFX_FLAG_REPEAT
70 };
71
72 // Various oneshots
73 sfx_system audio_system_balls_switching =
74 {
75 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
76 .name = "Balls Switching"
77 };
78
79 // Gameplay critical sounds eg. splitter sound rocking
80 sfx_system audio_system_balls_important =
81 {
82 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
83 .name = "Balls Gameplay"
84 };
85
86 // Suplemental sounds
87 sfx_system audio_system_balls_extra =
88 {
89 .vol = 1.f, .ch = 1, .vol_src = &audio_volume_sfx,
90 .name = "Balls Extra"
91 };
92
93 static void resource_load_main(void)
94 {
95 // Textures
96 vg_tex2d_init( texture_list, vg_list_size( texture_list ) );
97
98 ui_override_font( tex_monofur.name, 7 );
99
100 // Audio
101 sfx_set_init( &audio_tile_mod, NULL );
102 sfx_set_init( &audio_splitter, NULL );
103 sfx_set_init( &audio_rolls, NULL );
104 sfx_set_init( &audio_random, NULL );
105 }
106
107 static void resource_free_main(void)
108 {
109 vg_tex2d_free( texture_list, vg_list_size( texture_list ) );
110
111 sfx_set_free( &audio_tile_mod );
112 sfx_set_free( &audio_splitter );
113 sfx_set_free( &audio_rolls );
114 sfx_set_free( &audio_random );
115 }
116
117 // SHADERS
118 // ===========================================================================================================
119
120 SHADER_DEFINE( shader_tile_colour,
121
122 // VERTEX
123 "layout (location=0) in vec2 a_co;"
124 "uniform mat3 uPv;"
125 "uniform vec3 uOffset;"
126 ""
127 "void main()"
128 "{"
129 "gl_Position = vec4( uPv * vec3( a_co * uOffset.z + uOffset.xy, 1.0 ), 1.0 );"
130 "}",
131
132 // FRAGMENT
133 "out vec4 FragColor;"
134 "uniform vec4 uColour;"
135 ""
136 "void main()"
137 "{"
138 "FragColor = uColour;"
139 "}"
140 ,
141 UNIFORMS({ "uPv", "uOffset", "uColour" })
142 )
143
144 SHADER_DEFINE( shader_ball,
145 // VERTEX
146 "layout (location=0) in vec2 a_co;"
147 "uniform vec2 uOffset;"
148 "uniform mat3 uPv;"
149 ""
150 "out vec4 aTexCoords;"
151 ""
152 "void main()"
153 "{"
154 // Vertex transform
155 "vec3 worldpos = vec3( a_co * 0.5 - 0.25 + uOffset, 1.0 );"
156 "gl_Position = vec4( uPv * worldpos, 1.0 );"
157
158 // Create texture coords
159 "aTexCoords = vec4( a_co, worldpos.xy );"
160 "}",
161
162 // FRAGMENT
163 "out vec4 FragColor;"
164 ""
165 "uniform sampler2D uTexMain;"
166 "uniform vec3 uColour;"
167 "uniform vec2 uTexOffset;"
168 ""
169 "in vec4 aTexCoords;"
170 ""
171 "void main()"
172 "{"
173 "vec2 center_coords = aTexCoords.xy - 0.5;"
174 "vec2 center_coords_sqr = center_coords*center_coords;"
175 "float circle_factor = smoothstep( 0.07, 0.0625, center_coords_sqr.x+center_coords_sqr.y );"
176
177 "float bulge_amt = center_coords_sqr.x+center_coords_sqr.y;"
178 "vec2 warped_coords = aTexCoords.zw+uTexOffset - center_coords;"
179 "vec4 noise_sample = texture( uTexMain, warped_coords );"
180
181 "float rim_light = (center_coords_sqr.x+center_coords_sqr.y)*15.0;"
182
183 "vec2 shadow_coords = center_coords + vec2(0.02,0.07);"
184 "vec2 shadow_coords_sqr = shadow_coords*shadow_coords;"
185 "float shadow = exp(-((shadow_coords_sqr.x+shadow_coords_sqr.y)-0.0125)*15.0);"
186
187 "vec3 marble_comp = uColour*0.9 + (noise_sample.x*0.7+pow(rim_light,3.0)*2.0) * 0.1;"
188 "vec4 colour_comp = mix( vec4(0.74,0.53,0.34,shadow), vec4(marble_comp,1.0), circle_factor );"
189
190 "FragColor = colour_comp;"
191 "}"
192 ,
193 UNIFORMS({ "uTexMain", "uColour", "uOffset", "uPv", "uTexOffset" })
194 )
195
196 SHADER_DEFINE( shader_tile_main,
197 // VERTEX
198 "layout (location=0) in vec2 a_co;"
199 "uniform vec4 uOffset;" // Tile x/y, uv x/y
200 "uniform mat3 uPv;"
201 "uniform mat2 uSubTransform;"
202 ""
203 "out vec4 aTexCoords;"
204 "out vec2 aWorldCoords;"
205 ""
206 "vec2 hash22(vec2 p)"
207 "{"
208 "vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));"
209 "p3 += dot(p3, p3.yzx+33.33);"
210 "return fract((p3.xx+p3.yz)*p3.zy);"
211 "}"
212 ""
213 "void main()"
214 "{"
215 // Vertex transform
216 "vec2 subtransform = uSubTransform * (a_co-0.5) + 0.5;"
217 "vec3 worldpos = vec3( subtransform + uOffset.xy, 1.0 );"
218 "gl_Position = vec4( uPv * worldpos, 1.0 );"
219
220 // Create texture coords
221 "vec2 random_offset = floor(hash22(uOffset.xy) * 4.0) * 0.25;"
222 "vec2 edge_safe_coords = a_co * 0.98 + 0.01;"
223 "aTexCoords = vec4((edge_safe_coords + uOffset.zw) * 0.25, edge_safe_coords * 0.25 + random_offset );"
224 "aWorldCoords = worldpos.xy;"
225 "}",
226
227 // FRAGMENT
228 "out vec4 FragColor;"
229 ""
230 "uniform sampler2D uTexGlyphs;"
231 "uniform sampler2D uTexWood;"
232 "uniform float uGhost;"
233 "uniform float uForeground;"
234 "uniform vec2 uMousePos;"
235 "uniform vec4 uColour;"
236 ""
237 "in vec4 aTexCoords;"
238 "in vec2 aWorldCoords;"
239 ""
240 "void main()"
241 "{"
242 "vec3 shadowing_colour = vec3( 0.93, 0.88536, 0.8184 );"
243 "vec4 glyph = texture( uTexGlyphs, aTexCoords.xy );"
244 "vec4 wood = texture( uTexWood, aTexCoords.zw );"
245 "vec4 wood_secondary = texture( uTexWood, aTexCoords.zw + 0.25 );"
246 "vec3 wood_comp = mix( wood_secondary.rgb * shadowing_colour, wood.rgb, clamp( glyph.b * 2.0 - 1.0, 0.0, 1.0 ) );"
247
248 "vec3 shadows = mix( vec3( 0.85, 0.7344, 0.561 ), vec3(1.0,1.0,1.0), glyph.r );"
249
250 "vec4 output_regular = vec4( wood_comp * shadows, mix( glyph.a, glyph.b, uForeground ) );"
251
252 "float ghost_dist = clamp( 1.5 - distance(uMousePos, aWorldCoords), 0.0, 1.0 );"
253 "vec4 output_ghost = vec4( 1.0, 1.0, 1.0, glyph.g * ghost_dist );"
254
255 "FragColor = mix( output_regular, output_ghost, uGhost ) * uColour;"
256 "}"
257 ,
258 UNIFORMS({ "uPv", "uOffset", "uTexGlyphs", "uTexWood", "uSubTransform", "uGhost", "uMousePos", "uColour", "uForeground" })
259 )
260
261 SHADER_DEFINE( shader_background,
262 // VERTEX
263 "layout (location=0) in vec2 a_co;"
264 "uniform mat3 uPv;"
265 "uniform vec3 uOffset;"
266 ""
267 "out vec2 aTexCoords;"
268 ""
269 "void main()"
270 "{"
271 "vec2 world_pos = a_co * uOffset.z + uOffset.xy;"
272 "gl_Position = vec4( uPv * vec3( world_pos, 1.0 ), 1.0 );"
273 "aTexCoords = a_co;"
274 "}",
275
276 // FRAGMENT
277 "out vec4 FragColor;"
278 ""
279 "uniform sampler2D uTexMain;"
280 "uniform sampler2D uSamplerNoise;"
281 "uniform float uVariance;"
282 ""
283 "in vec2 aTexCoords;"
284 ""
285 "void main()"
286 "{"
287 "float ao_accum = 0.0;"
288 "for( int i=0; i<10; ++i )"
289 "{"
290 "vec2 random_noise = (texture( uSamplerNoise, aTexCoords * 20.0 + float(i) * 0.2 ).xy - vec2( 0.5, 0.5 )) * uVariance;"
291 "vec4 background = texture( uTexMain, aTexCoords + random_noise );"
292 "ao_accum += background.r * clamp((1.0 - length( random_noise )), 0.0, 1.0);"
293 "}"
294 "ao_accum *= 0.15;"
295
296 "vec4 data_this_tile = texture( uTexMain, aTexCoords );"
297
298 "ao_accum -= data_this_tile.r;"
299
300 "vec3 colour_main = vec3( 0.369768, 0.3654, 0.42 );"
301
302 "vec2 square_coords = fract( aTexCoords * 64.0 );"
303 "vec2 grid_coords = abs( square_coords - 0.5 );"
304 "float edge_contrast = (1.0-ao_accum*0.2);"
305
306 "float gridline = step( 0.49, max(grid_coords.x,grid_coords.y) );"
307 "float gridline_fadeout = min(max(edge_contrast-1.0, 0.0)*40.0 + data_this_tile.g,10.0);"
308
309 "FragColor = vec4( colour_main * edge_contrast + gridline * 0.02 * gridline_fadeout, 1.0 );"
310 "}"
311 ,
312 UNIFORMS({ "uPv", "uOffset", "uTexMain", "uVariance", "uSamplerNoise" })
313 )
314
315 SHADER_DEFINE( shader_wire,
316 // VERTEX
317 "layout (location=0) in vec2 a_co;"
318 "uniform vec3 uStart;"
319 "uniform vec3 uEnd;"
320 "uniform mat3 uPv;"
321 "uniform float uCurve;"
322 ""
323 "out vec2 aTexCoords;"
324 ""
325 "vec3 sample_curve_time( float t )"
326 "{"
327 "vec3 line_coord = mix( uStart, uEnd, t );"
328
329 "float curve_amt = 1.0-(pow((t*2.0-1.0),2.0));"
330 "return vec3( line_coord.x, line_coord.y - curve_amt*uCurve, line_coord.z );"
331 "}"
332 ""
333 "void main()"
334 "{"
335 // Vertex transform
336 "vec3 p0 = sample_curve_time( a_co.x );"
337 "vec3 p1 = sample_curve_time( a_co.x + 0.025 );"
338
339 "vec2 line_tangent = normalize(p1.xy-p0.xy);"
340 "vec2 line_normal = vec2( -line_tangent.y, line_tangent.x );"
341
342 "vec2 worldfinal = p0.xy + line_normal*a_co.y*p0.z;"
343
344 "gl_Position = vec4( uPv * vec3(worldfinal, 1.0), 1.0 );"
345
346 // Create texture coords (todo: include stretch adjusted coords?)
347 "aTexCoords = vec2( a_co.x, a_co.y + 0.5 );"
348 "}",
349
350 // FRAGMENT
351 "out vec4 FragColor;"
352 ""
353 "uniform sampler2D uTexMain;"
354 "uniform vec4 uColour;"
355 ""
356 "in vec2 aTexCoords;"
357 ""
358 "void main()"
359 "{"
360 "FragColor = uColour;"
361 "}"
362 ,
363 UNIFORMS({ "uPv", "uColour", "uTexMain", "uStart", "uEnd", "uCurve" })
364 )
365
366
367 void vg_register(void)
368 {
369 SHADER_INIT( shader_tile_colour );
370 SHADER_INIT( shader_tile_main );
371 SHADER_INIT( shader_ball );
372 SHADER_INIT( shader_background );
373 SHADER_INIT( shader_wire );
374 }
375
376 /*
377 0000 0 | 0001 1 | 0010 2 | 0011 3
378 | | | | |
379 X | X= | X | X=
380 | | |
381 0100 4 | 0101 5 | 0110 6 | 0111 7
382 | | | | |
383 =X | =X= | =X | =X=
384 | | |
385 1000 8 | 1001 9 | 1010 10 | 1011 11
386 | | | | |
387 X | X= | X | X=
388 | | | | | | |
389 1100 12 | 1101 13 | 1110 14 | 1111 15
390 | | | | |
391 =X | =X= | =X | =X=
392 | | | | | | |
393 */
394
395 float const MESH_NUMBER_0[] = {
396 #include "fonts/numbers/n0.h"
397 };
398
399 float const MESH_NUMBER_1[] = {
400 #include "fonts/numbers/n1.h"
401 };
402
403 float const MESH_NUMBER_2[] = {
404 #include "fonts/numbers/n2.h"
405 };
406
407 float const MESH_NUMBER_3[] = {
408 #include "fonts/numbers/n3.h"
409 };
410
411 float const MESH_NUMBER_4[] = {
412 #include "fonts/numbers/n4.h"
413 };
414
415 float const MESH_NUMBER_5[] = {
416 #include "fonts/numbers/n5.h"
417 };
418
419 float const MESH_NUMBER_6[] = {
420 #include "fonts/numbers/n6.h"
421 };
422
423 float const MESH_NUMBER_7[] = {
424 #include "fonts/numbers/n7.h"
425 };
426
427 float const MESH_NUMBER_8[] = {
428 #include "fonts/numbers/n8.h"
429 };
430
431 float const MESH_NUMBER_9[] = {
432 #include "fonts/numbers/n9.h"
433 };
434
435 float const MESH_NUMBERS_BUFFER[] =
436 {
437 #include "fonts/numbers/n0.h"
438 #include "fonts/numbers/n1.h"
439 #include "fonts/numbers/n2.h"
440 #include "fonts/numbers/n3.h"
441 #include "fonts/numbers/n4.h"
442 #include "fonts/numbers/n5.h"
443 #include "fonts/numbers/n6.h"
444 #include "fonts/numbers/n7.h"
445 #include "fonts/numbers/n8.h"
446 #include "fonts/numbers/n9.h"
447 };
448
449 #define MESH_NUMBER_DIVISOR 6
450
451 u32 const MESH_NUMBERS_OFFSETS[][2] =
452 {
453 {
454 0,
455 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR
456 },
457 {
458 vg_list_size( MESH_NUMBER_0 ) / MESH_NUMBER_DIVISOR,
459 vg_list_size( MESH_NUMBER_1 ) / MESH_NUMBER_DIVISOR
460 },
461 {
462 (
463 vg_list_size( MESH_NUMBER_0 ) +
464 vg_list_size( MESH_NUMBER_1 )
465 ) / MESH_NUMBER_DIVISOR,
466 vg_list_size( MESH_NUMBER_2 ) / MESH_NUMBER_DIVISOR
467 },
468 {
469 (
470 vg_list_size( MESH_NUMBER_0 ) +
471 vg_list_size( MESH_NUMBER_1 ) +
472 vg_list_size( MESH_NUMBER_2 )
473 ) / MESH_NUMBER_DIVISOR,
474 vg_list_size( MESH_NUMBER_3 ) / MESH_NUMBER_DIVISOR
475 },
476 {
477 (
478 vg_list_size( MESH_NUMBER_0 ) +
479 vg_list_size( MESH_NUMBER_1 ) +
480 vg_list_size( MESH_NUMBER_2 ) +
481 vg_list_size( MESH_NUMBER_3 )
482 ) / MESH_NUMBER_DIVISOR,
483 vg_list_size( MESH_NUMBER_4 ) / MESH_NUMBER_DIVISOR
484 },
485 {
486 (
487 vg_list_size( MESH_NUMBER_0 ) +
488 vg_list_size( MESH_NUMBER_1 ) +
489 vg_list_size( MESH_NUMBER_2 ) +
490 vg_list_size( MESH_NUMBER_3 ) +
491 vg_list_size( MESH_NUMBER_4 )
492 ) / MESH_NUMBER_DIVISOR,
493 vg_list_size( MESH_NUMBER_5 ) / MESH_NUMBER_DIVISOR
494 },
495 {
496 (
497 vg_list_size( MESH_NUMBER_0 ) +
498 vg_list_size( MESH_NUMBER_1 ) +
499 vg_list_size( MESH_NUMBER_2 ) +
500 vg_list_size( MESH_NUMBER_3 ) +
501 vg_list_size( MESH_NUMBER_4 ) +
502 vg_list_size( MESH_NUMBER_5 )
503 ) / MESH_NUMBER_DIVISOR,
504 vg_list_size( MESH_NUMBER_6 ) / MESH_NUMBER_DIVISOR
505 },
506 {
507 (
508 vg_list_size( MESH_NUMBER_0 ) +
509 vg_list_size( MESH_NUMBER_1 ) +
510 vg_list_size( MESH_NUMBER_2 ) +
511 vg_list_size( MESH_NUMBER_3 ) +
512 vg_list_size( MESH_NUMBER_4 ) +
513 vg_list_size( MESH_NUMBER_5 ) +
514 vg_list_size( MESH_NUMBER_6 )
515 ) / MESH_NUMBER_DIVISOR,
516 vg_list_size( MESH_NUMBER_7 ) / MESH_NUMBER_DIVISOR
517 },
518 {
519 (
520 vg_list_size( MESH_NUMBER_0 ) +
521 vg_list_size( MESH_NUMBER_1 ) +
522 vg_list_size( MESH_NUMBER_2 ) +
523 vg_list_size( MESH_NUMBER_3 ) +
524 vg_list_size( MESH_NUMBER_4 ) +
525 vg_list_size( MESH_NUMBER_5 ) +
526 vg_list_size( MESH_NUMBER_6 ) +
527 vg_list_size( MESH_NUMBER_7 )
528 ) / MESH_NUMBER_DIVISOR,
529 vg_list_size( MESH_NUMBER_8 ) / MESH_NUMBER_DIVISOR
530 },
531 {
532 (
533 vg_list_size( MESH_NUMBER_0 ) +
534 vg_list_size( MESH_NUMBER_1 ) +
535 vg_list_size( MESH_NUMBER_2 ) +
536 vg_list_size( MESH_NUMBER_3 ) +
537 vg_list_size( MESH_NUMBER_4 ) +
538 vg_list_size( MESH_NUMBER_5 ) +
539 vg_list_size( MESH_NUMBER_6 ) +
540 vg_list_size( MESH_NUMBER_7 ) +
541 vg_list_size( MESH_NUMBER_8 )
542 ) / MESH_NUMBER_DIVISOR,
543 vg_list_size( MESH_NUMBER_9 ) / MESH_NUMBER_DIVISOR
544 }
545 };
546
547 struct cmp_level
548 {
549 const char *map_name;
550 const char *title;
551 const char *description;
552
553 int serial_id;
554 };
555
556 struct cmp_level cmp_levels_tutorials[] =
557 {
558 {
559 .title = "PRINCIPLE 1",
560 .map_name = "cmp_t01",
561 .description = "Utilize basic transport methods",
562
563 .serial_id = 0
564 },
565 {
566 .title = "PRINCIPLE 2",
567 .map_name = "cmp_t02",
568 .description = "Utilize the twisty turny(TM) piece",
569
570 .serial_id = 1
571 },
572 {
573 .title = "PRINCIPLE 3",
574 .map_name = "cmp_t03",
575 .description = "Merge transport into one",
576
577 .serial_id = 2
578 },
579 {
580 .title = "PRINCIPLE 4",
581 .map_name = "cmp_t04",
582 .description = "Some stages require multiple runs to succeed in order to pass",
583
584 .serial_id = 12
585 }
586 };
587
588 struct cmp_level cmp_levels_basic[] =
589 {
590 {
591 .title = "SUBDIVISION 1",
592 .map_name = "cmp_b01",
593 .description = "Simple maths, branching required.",
594
595 .serial_id = 3
596 },
597 {
598 .title = "SUBDIVISION 2",
599 .map_name = "cmp_b02",
600 .description = "Simple maths. Futher.",
601
602 .serial_id = 4
603 },
604 {
605 .title = "RESTRUCTURE",
606 .map_name = "cmp_b03",
607 .description = "Not so simple swap",
608
609 .serial_id = 5
610 },
611 {
612 .title = "SERIALIZE",
613 .map_name = "cmp_b04",
614 .description = "Merge and sort",
615
616 .serial_id = 6
617 },
618 {
619 .title = "PATTERNS 1",
620 .map_name = "cmp_b05",
621 .description = "Replicate",
622
623 .serial_id = 7
624 },
625 {
626 .title = "PATTERNS 2",
627 .map_name = "cmp_b06",
628 .description = "Replicate MORE",
629
630 .serial_id = 8
631 },
632 {
633 .title = "MIGHTY CONSUMER",
634 .map_name = "cmp_b07",
635 .description = "Build a greedy system",
636
637 .serial_id = 9
638 },
639 {
640 .title = "ENCRYPTED 1",
641 .map_name = "cmp_b08",
642 .description = "Some configurations may not be valid",
643
644 .serial_id = 10
645 },
646 {
647 .title = "REVERSE",
648 .map_name = "cmp_b09",
649 .description = "Reverse the incoming order. Always length 4",
650
651 .serial_id = 11
652 },
653 {
654 .title = "PRINCIPLE 5",
655 .map_name = "cmp_b10",
656 .description =
657 "The competent engineers among you may have already\n"
658 "spotted and utilized these parts of the system\n"
659 "\n"
660 "We forgot to include the relevant principle tasks\n"
661 "as part of your training package, you will now be\n"
662 "tasked to complete them",
663
664 .serial_id = 15
665 },
666 {
667 .title = "ROUTING PROBLEM",
668 .map_name = "cmp_routing",
669 .description =
670 "Things can get a little chaotic on tight boards,\n"
671 "Do your best to utilize principle 5 to get the job\n"
672 "done.",
673
674 .serial_id = 16
675 },
676 {
677 .title = "PRINCIPLE 6",
678 .map_name = "cmp_b11",
679 .description =
680 "While hovering over a simple tile peice, right click\n"
681 "and drag to start creating a wire. These can be\n"
682 "connected to the left, or right recieving pins of a\n"
683 "Twisty Turny(TM) peice.\n"
684 "\n"
685 "Once connected, the Twisty Turny(TM) will no longer\n"
686 "'flip flop' as marbles run through them, but instead\n"
687 "be set to left or right rotating only. As indicated\n"
688 "by the status arrow beneath them\n"
689 "\n"
690 "When the left or right slot is triggered, the Twisty\n"
691 "Turny(TM) will switch modes according to that input.\n"
692 "\n"
693 "Trigger wires apply instantaneously, however if both\n"
694 "the left and right inputs are recieved at the same\n"
695 "time, this results in no operation being performed,\n"
696 "and no state changes take place in the Twisty Turny(TM)\n",
697
698 .serial_id = 17
699 },
700 {
701 .title = "NOT GATE",
702 .map_name = "cmp_not",
703 .description =
704 "Test your knowledge of triggers, build an 'NOT GATE'\n"
705 "emulated by marble logic.",
706
707 .serial_id = 18
708 },
709 {
710 .title = "AND GATE",
711 .map_name = "cmp_and",
712 .description =
713 "A slightly more complicated gate, but shouldn't be\n"
714 "too difficult for your skillset.",
715
716 .serial_id = 19
717 },
718 {
719 .title = "QUALIFICATION PROJECT",
720 .map_name = "cmp_grad",
721 .description =
722 "There's no instructions here, resolve and complete this\n"
723 "task to qualify yourself as an official marble engineer",
724 .serial_id = 20
725 }
726 };
727
728 struct cmp_level cmp_levels_grad[] =
729 {
730 {
731 .title = "SORT",
732 .map_name = "cmp_i01",
733 .description =
734 "Device a scheme to filter and sort the inputs. If you\n"
735 "believe you lack the tools required to solve this one,\n"
736 "take a harder look at the inputs.",
737
738 .serial_id = 13
739 },
740 {
741 .title = "THIRDS",
742 .map_name = "cmp_i02",
743 .description =
744 "Spit your inputs up into a third of its value\n"
745 "Is this possible? -HG",
746
747 .serial_id = 14
748 },
749 {
750 .title = "XOR CHIP",
751 .map_name = "cmp_xor",
752 .description =
753 "Significantly more complicated than an AND or NOT gate,\n"
754 "but possible.",
755 .serial_id = 21
756 },
757 {
758 .title = "SECRET CODE",
759 .map_name = "cmp_secret",
760 .description =
761 "Only one input should send an unlock signal marble to\n"
762 "the output.\n"
763 "The code: 100110",
764 .serial_id = 22
765 }
766 };