//Uses fixed-point. RegDefault("ZealOS/RawHide", "F64 best_score=9999;\n"); RegExe("ZealOS/RawHide"); F64 t0, tf; I64 outside_count; #define MAP_WIDTH 1000 #define MAP_HEIGHT 1000 #define FENCE_WIDTH 320 #define FENCE_HEIGHT 200 #define MAP_BORDER 3 CDC *map_dc; #define GATE_WIDTH 22 #define GATE_HEIGHT 7 F64 gate_theta, gate_t; <1>/* Graphics Not Rendered in HTML */ <2>/* Graphics Not Rendered in HTML */ <3>/* Graphics Not Rendered in HTML */ <4>/* Graphics Not Rendered in HTML */ <5>/* Graphics Not Rendered in HTML */ <6>/* Graphics Not Rendered in HTML */ <7>/* Graphics Not Rendered in HTML */ <8>/* Graphics Not Rendered in HTML */ <9>/* Graphics Not Rendered in HTML */ <10>/* Graphics Not Rendered in HTML */ #define ANIMAL_WIDTH 20 #define ANIMAL_HEIGHT 16 U8 *cow_imgs[4] = {<1>, <2>, <3>, <2>}, *bull_imgs[4] = {<4>, <5>, <6>, <5>}, *horse_imgs[4] = {<7>, <8>, <7>, <8>}; #define ANIMALS_NUM 100 class Animal { I64 num, x, y, dx, dy; U8 **imgs; U32 buddy; U8 type, frame0; Bool dead, pad; } *a; //************************************ #define WATERFALL_HEIGHT (MAP_HEIGHT / 20) #define WATERFALL_DROPS 512 #define WATERFALL_ACCELERATION 10 I32 *r_x, *r_width, *wfd_x; F64 *wfd_t0, waterfall_tf; I64 waterfall_x, waterfall_y, waterfall_width; U0 RiverNew() { r_x = MAlloc(MAP_HEIGHT * sizeof(I32)); r_width = MAlloc(MAP_HEIGHT * sizeof(I32)); wfd_x = MAlloc(WATERFALL_DROPS * sizeof(I32)); wfd_t0 = MAlloc(WATERFALL_DROPS * sizeof(F64)); waterfall_tf = Sqrt(2 * WATERFALL_HEIGHT / WATERFALL_ACCELERATION); } U0 RiverMake() { I64 i, x = 2 * MAP_WIDTH << 32 / 3, y, dx = 0, w = 15 << 32; waterfall_y = (MAP_HEIGHT - WATERFALL_HEIGHT) / 2 * Rand + (MAP_HEIGHT - WATERFALL_HEIGHT) / 4; for (y = MAP_BORDER; y < MAP_HEIGHT-MAP_BORDER; y++) { r_x[y] = x.i32[1]; r_width[y] = w.i32[1]; if (waterfall_y - 5 < y < waterfall_y + WATERFALL_HEIGHT + 5) { waterfall_width = r_width[y]; waterfall_x = r_x[y] - waterfall_width / 2; } else { dx = ClampI64(dx + RandI32 / 64, -I32_MAX, I32_MAX) - I32_MAX / 256; w = ClampI64(w + RandI32 * 2, 10 * U32_MAX, 150 * U32_MAX); x += dx; } } for (i = 0; i < WATERFALL_DROPS; i++) { wfd_x[i] = Rand * waterfall_width + waterfall_x; wfd_t0[i] = tS - Rand * waterfall_tf; } //Plot waterfall cliff Sprite3B(map_dc, waterfall_x, waterfall_y, 0, <10>); //Plot sand bar x = 0; for (y = MAP_BORDER; y < MAP_HEIGHT - MAP_BORDER; y++) { if (!(waterfall_y - 9 < y < waterfall_y + WATERFALL_HEIGHT + 9)) { map_dc->color = YELLOW; map_dc->thick = r_width[y] + 10; GrPlot3(map_dc, r_x[y] + x.i32[1], y, 0); } x = ClampI64(x+RandI32, -6 * U32_MAX, 6 * U32_MAX); } //Plot water for (y = MAP_BORDER; y < MAP_HEIGHT - MAP_BORDER; y++) { map_dc->color = BLUE; map_dc->thick = r_width[y]; GrPlot3(map_dc, r_x[y], y, 0); } } U0 RiverDel() { Free(r_x); Free(r_width); Free(wfd_x); Free(wfd_t0); } //************************************ class RiverDrop { RiverDrop *next, *last; I64 y, dx, dy; } rd_head; Bool rd_lock; U0 RiverDropsDel() { while (LBts(&rd_lock, 0)) Yield; QueueDel(&rd_head, TRUE); QueueInit(&rd_head); LBtr(&rd_lock, 0); } U0 RiverDropsNext(CTask *mem_task) { RiverDrop *tmpr, *tmpr1; while (LBts(&rd_lock, 0)) Yield; tmpr = rd_head.next; while (tmpr != &rd_head) { tmpr1 = tmpr->next; if (++tmpr->y >= MAP_HEIGHT - MAP_BORDER) { QueueRemove(tmpr); Free(tmpr); } else { do { if (RandU16 & 1 && GrPeek(map_dc, r_x[tmpr->y] + tmpr->dx, tmpr->y + tmpr->dy) == BLUE) break; tmpr->dx = ClampI64(tmpr->dx + RandU16 % 3 - 1, -r_width[tmpr->y] / 2, r_width[tmpr->y] / 2); tmpr->dy = ClampI64(tmpr->dy + RandU16 % 3 - 1, -r_width[tmpr->y] / 2, r_width[tmpr->y] / 2); } while (GrPeek(map_dc, r_x[tmpr->y] + tmpr->dx, tmpr->y + tmpr->dy) != BLUE && GrPeek(map_dc, r_x[tmpr->y], tmpr->y) == BLUE);//Might be reiniting } tmpr = tmpr1; } tmpr = MAlloc(sizeof(RiverDrop), mem_task); tmpr->y = MAP_BORDER; tmpr->dx = 0; tmpr->dy = 0; QueueInsert(tmpr, rd_head.last); LBtr(&rd_lock, 0); } U0 RiverDropsDraw(CDC *dc, I64 cx, I64 cy) { I64 i; F64 t = tS; RiverDrop *tmpr; while (LBts(&rd_lock, 0)) Yield; tmpr = rd_head.next; dc->color = LTBLUE; while (tmpr != &rd_head) { GrPlot(dc, r_x[tmpr->y] + tmpr->dx-cx, tmpr->y + tmpr->dy-cy); tmpr = tmpr->next; } LBtr(&rd_lock, 0); dc->color = WHITE; for (i = 0; i < WATERFALL_DROPS; i++) GrPlot(dc, wfd_x[i] - cx, waterfall_y + 0.5 * WATERFALL_ACCELERATION * Sqr(waterfall_tf * Saw(t - wfd_t0[i], waterfall_tf)) - cy); } //************************************ U0 DrawIt(CTask *task, CDC *dc) { static I64 last_pos_x = 0; static Bool left = TRUE; F64 t; I64 i, frame=4 * tS, cx = (MAP_WIDTH - task->pix_width) / 2, cy = (MAP_HEIGHT - task->pix_height) / 2; if (task->scroll_x + cx < 0) task->scroll_x = -cx; if (task->scroll_x + cx > MAP_WIDTH - task->pix_width) task->scroll_x = MAP_WIDTH - task->pix_width - cx; if (task->scroll_y + cy < 0) task->scroll_y = -cy; if (task->scroll_y + cy > MAP_HEIGHT - task->pix_height) task->scroll_y = MAP_HEIGHT - task->pix_height - cy; map_dc->flags |= DCF_NO_TRANSPARENTS; GrBlot(dc, -cx, -cy, map_dc); RiverDropsDraw(dc, cx, cy); for (i = 0; i < ANIMALS_NUM; i++) if (!a[i].dead) { if (a[i].dx < 0) { dc->flags |= DCF_JUST_MIRROR | DCF_SYMMETRY; DCSymmetrySet(dc, a[i].x.i32[1] - cx, 0, a[i].x.i32[1] - cx, 1); } Sprite3(dc, a[i].x.i32[1] - cx, a[i].y.i32[1] - cy, 0, a[i].imgs[(frame + a[i].frame0) & 3]); dc->flags &= ~(DCF_JUST_MIRROR|DCF_SYMMETRY); } if (mouse.pos.x - last_pos_x > 0) left = FALSE; else if (mouse.pos.x - last_pos_x < 0) left = TRUE; if (left) { dc->flags |= DCF_JUST_MIRROR | DCF_SYMMETRY; DCSymmetrySet(dc, mouse.pos.x - task->pix_left - task->scroll_x, 0, mouse.pos.x - task->pix_left - task->scroll_x, 1); } Sprite3(dc, mouse.pos.x - task->pix_left - task->scroll_x, mouse.pos.y - task->pix_top - task->scroll_y, 0, horse_imgs[frame & 3]); dc->flags &= ~(DCF_JUST_MIRROR|DCF_SYMMETRY); last_pos_x = mouse.pos.x; if (tf) { dc->color = RED; t = tf - t0; if (Blink) GrPrint(dc, (task->pix_width - FONT_WIDTH * 14) >> 1 - task->scroll_x, (task->pix_height - FONT_HEIGHT) >> 1 - task->scroll_y, "Game Completed"); } else { dc->color = BLACK; t = tS - t0; } GrPrint(dc, -task->scroll_x, -task->scroll_y, "Outside:%03d Time:%7.2fs Best:%7.2fs", outside_count, t, best_score); } U0 BuddySel(I64 i) { I64 b, best_b = i, score, best_score = I64_MAX; for (b = 0; b < ANIMALS_NUM; b++) { if (b != i && !a[b].dead) { score = RandU32 % (512 * 512) + SqrI64(a[b].x.i32[1] - a[i].x.i32[1]) + SqrI64(a[b].y.i32[1] - a[i].y.i32[1]); if (score < best_score) { best_score = score; best_b = b; } } } a[i].buddy = best_b; } U0 RedrawGate() { F64 tt = tS - gate_t; I64 x1 = FENCE_WIDTH - 63, y1 = FENCE_HEIGHT - 1, dx, dy; if (tt < 0.5) gate_theta = Clamp(gate_theta + 0.02, 0, pi / 2); else if (tt > 5.0) gate_theta = Clamp(gate_theta - 0.02, 0, pi / 2); dx = GATE_WIDTH * Cos(gate_theta); dy = -0.8 * GATE_WIDTH * Sin(gate_theta); map_dc->color = LTGREEN; GrRect(map_dc, x1, y1 - 0.8 * GATE_WIDTH - GATE_HEIGHT, 46, 0.8 * GATE_WIDTH + GATE_HEIGHT + 3); map_dc->color = BLACK; GrLine(map_dc, x1, y1, x1 + dx, y1 + dy); GrLine(map_dc, x1, y1, x1, y1 - GATE_HEIGHT); GrLine(map_dc, x1 + dx, y1 + dy, x1 + dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1, y1 - GATE_HEIGHT, x1 + dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1, y1, x1 + dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1, y1 - GATE_HEIGHT, x1 + dx, y1 + dy); GrLine(map_dc, x1 + 45, y1, x1 + 45 - dx, y1 + dy); GrLine(map_dc, x1 + 45, y1, x1 + 45, y1 - GATE_HEIGHT); GrLine(map_dc, x1 + 45 - dx, y1 + dy, x1 + 45 - dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1 + 45, y1 - GATE_HEIGHT, x1 + 45 - dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1 + 45, y1, x1 + 45 - dx, y1 + dy - GATE_HEIGHT); GrLine(map_dc, x1 + 45, y1 - GATE_HEIGHT, x1 + 45 - dx, y1 + dy); } Bool CheckMap(I64 x, I64 y) { I64 i, j, c; if (SqrI64(x - (waterfall_x + waterfall_width / 2)) >> 1 + SqrI64(y - (waterfall_y + WATERFALL_HEIGHT / 2)) < 2500) return FALSE; for (j = -4; j <= 2; j++) for (i = -4; i <= 4; i++) { c = GrPeek(map_dc, x + i, y + j); if (c == LTGRAY || c == BLACK) return FALSE; } return TRUE; } U0 AnimateTask(CTask *parent) { I64 i, cx, cy, cursor_x, cursor_y, dd, ddx, ddy, count, max_speed = I64_MAX, updates = 0, my_outside_count; F64 f, d, dx, dy, s, stress; Animal *tmpa, *tmpa1; while (TRUE) { max_speed = ClampU64(max_speed, U32_MAX / 3, 200 * U32_MAX); cx = (MAP_WIDTH - parent->pix_width) / 2, cy = (MAP_HEIGHT - parent->pix_height) / 2; cursor_x = mouse.pos.x + cx - parent->pix_left - parent->scroll_x; cursor_y = mouse.pos.y + cy - parent->pix_top - parent->scroll_y; count = 0; stress = 0; my_outside_count = 0; if (cursor_x < FENCE_WIDTH && cursor_y < FENCE_HEIGHT) gate_t = tS; RedrawGate; for (i = 0; i < ANIMALS_NUM; i++) { tmpa = &a[i]; if (!tmpa->dead) {//Move away from horse ddx = tmpa->x.i32[1]-cursor_x; ddy = tmpa->y.i32[1]-cursor_y; if (dd = SqrI64(ddx) + SqrI64(ddy)) { d = Sqrt(dd); dx = ddx / d; dy = ddy / d; f = 5.0e2 * U32_MAX / dd; tmpa->dx += f * dx; tmpa->dy += f * dy; } //Resel buddy about every ANIMALS_NUM*10ms=5.12 seconds tmpa1 = &a[tmpa->buddy]; if (tmpa1->dead || i == updates % ANIMALS_NUM) { BuddySel(i); tmpa1 = &a[tmpa->buddy]; } //Move toward buddy ddx = tmpa->x.i32[1] - tmpa1->x.i32[1]; ddy = tmpa->y.i32[1] - tmpa1->y.i32[1]; if (dd = SqrI64(ddx) + SqrI64(ddy)) { d = Sqrt(dd); s = d ` 1.25 - 80; stress += Abs(s); dx = ddx / d; dy = ddy / d; f = -0.001 * s * U32_MAX; tmpa->dx += f * dx; tmpa->dy += f * dy; } //Make velocity similar to buddy tmpa->dx += 0.1 * (tmpa1->dx - tmpa->dx); tmpa->dy += 0.1 * (tmpa1->dy - tmpa->dy); //Add random movement, limit speed and dampen speed tmpa->dx = 0.995 * ClampI64(tmpa->dx + RandI32 / 32, -max_speed, max_speed); tmpa->dy = 0.995 * ClampI64(tmpa->dy + RandI32 / 32, -max_speed, max_speed); //Slow in river if (GrPeek(map_dc, tmpa->x.i32[1], tmpa->y.i32[1]) != LTGREEN) { tmpa->dx /= 2; tmpa->dy /= 2; } if (CheckMap((tmpa->x + tmpa->dx) >> 32, (tmpa->y + tmpa->dy) >> 32)) { tmpa->x += tmpa->dx; tmpa->y += tmpa->dy; } //Keep on map if (!(MAP_BORDER + ANIMAL_WIDTH / 2 <= tmpa->x.i32[1] < MAP_WIDTH - MAP_BORDER - ANIMAL_WIDTH / 2)) { tmpa->x -= tmpa->dx; tmpa->dx = -tmpa->dx; } if (!(MAP_BORDER + ANIMAL_HEIGHT <= tmpa->y.i32[1] < MAP_HEIGHT - MAP_BORDER)) { tmpa->y -= tmpa->dy; tmpa->dy = -tmpa->dy; } count++; if (tmpa->x >> 32 >= FENCE_WIDTH || tmpa->y >> 32 >= FENCE_HEIGHT) my_outside_count++; } } outside_count = my_outside_count; if (!(updates & 15)) RiverDropsNext(parent); if (!tf && !outside_count) { tf = tS; music.mute = TRUE; Sound(86); Sleep(200); Sound; Sleep(100); if (tf - t0 < best_score) { best_score = tf - t0; Sound(86); Sleep(200); Sound; Sleep(100); } music.mute = FALSE; } updates++; if (count) stress /= count; else stress = 0; if (stress > 100.0) { Yield; max_speed = stress / 5.0 * U32_MAX; //Converge faster at start-up } else { Sleep(10); max_speed = 0; //Will be set to normal max speed } } } U0 SongTask(I64) {//Randomly generated (by God :-) Fs->task_end_cb = &SoundTaskEndCB; MusicSettingsReset; while (TRUE) { Play("5qC4etG5DC4B5DCECFqFC4sA5D4A5D4qB"); Play("5C4etG5DC4B5DCECFqFC4sA5D4A5D4qB"); Play("4sGAGA5qG4etG5GD4eBBqB5F4eBA5qE"); Play("4sGAGA5qG4etG5GD4eBBqB5F4eBA5qE"); } } U0 ReInit() { I64 i; RiverDropsDel; map_dc->color = LTGREEN; GrRect(map_dc, 2, 2, MAP_WIDTH - 4, MAP_HEIGHT - 4); RiverMake; //Plot fence for (i = FENCE_WIDTH; i > 0; i -= 16) Sprite3(map_dc, i, FENCE_HEIGHT, 0, <9>); map_dc->thick = 1; map_dc->color = BROWN; for (i = 0; i < FENCE_HEIGHT - 16; i += 16) GrLine(map_dc, FENCE_WIDTH - 1, i, FENCE_WIDTH - 1, i + 7); map_dc->color = LTGRAY; GrLine(map_dc, FENCE_WIDTH, 0, FENCE_WIDTH, FENCE_HEIGHT - 6); RedrawGate; map_dc->thick = MAP_BORDER; map_dc->color = RED; GrBorder(map_dc, MAP_BORDER / 2, MAP_BORDER / 2, MAP_WIDTH - (MAP_BORDER + 1) / 2, MAP_HEIGHT - (MAP_BORDER + 1) / 2); for (i = MAP_BORDER; i <= MAP_HEIGHT - MAP_BORDER; i++) RiverDropsNext(Fs); MemSet(a, 0, ANIMALS_NUM * sizeof(Animal)); for (i = 0; i < ANIMALS_NUM; i++) { a[i].num = i; do { a[i].x = (64 + RandU32 % (MAP_WIDTH - 128)) << 32; a[i].y = (64 + RandU32 % (MAP_WIDTH - 128)) << 32; } while (!CheckMap(a[i].x >> 32, a[i].y >> 32)); if (i & 1) a[i].imgs = cow_imgs; else a[i].imgs = bull_imgs; a[i].frame0 = RandU16 & 3; BuddySel(i); } outside_count = ANIMALS_NUM; gate_t = 0; gate_theta = 0; t0 = tS; tf = 0; } U0 Init() { RiverNew; rd_lock = 0; QueueInit(&rd_head); map_dc = DCNew(MAP_WIDTH, MAP_HEIGHT); a = MAlloc(ANIMALS_NUM * sizeof(Animal)); ReInit; } U0 CleanUp() { DCDel(map_dc); Free(a); RiverDropsDel; RiverDel; } U0 RawHide() { I64 message_code, arg1, arg2; SettingsPush; //See SettingsPush MenuPush( "File {" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Play {" " Restart(,'\n');" "}" ); Fs->song_task = Spawn(&SongTask, NULL, "Song",, Fs); PopUpOk( "Coral the cattle. The coral is in the\n" "upper-left corner if you scroll.\n\n" "Keep holding the $GREEN$<CTRL>$FG$ key and\n" "scroll with $GREEN${CTRL-Left Grab}$FG$."); Fs->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_BORDER - WIF_SELF_GRAB_SCROLL - WIF_FOCUS_TASK_MENU; AutoComplete; WinBorder; WinMax; DocCursor; DocClear; Init; PaletteSetLight(FALSE); Fs->animate_task = Spawn(&AnimateTask, Fs, "Animate",, Fs); Fs->draw_it = &DrawIt; try { while (TRUE) { message_code = MessageGet(&arg1, &arg2, 1 << MESSAGE_KEY_DOWN + 1 << MESSAGE_MS_L_DOWN + 1 << MESSAGE_MS_R_DOWN); switch (message_code) { case MESSAGE_MS_L_DOWN: //Doesn't do anything, yet. break; case MESSAGE_MS_R_DOWN: //Doesn't do anything, yet. break; case MESSAGE_KEY_DOWN: switch (arg1) { case '\n': ReInit; break; case CH_SHIFT_ESC: case CH_ESC: goto rh_done; } break; } } rh_done: MessageGet(,, 1 << MESSAGE_KEY_UP); } catch PutExcept; SettingsPop; CleanUp; MenuPop; RegWrite("ZealOS/RawHide", "F64 best_score=%5.4f;\n", best_score); } RawHide;