#define VR_ONE_FRIENDLY_UNIT 0 #define VR_UPDATE_FRIENDLY_UNIT 1 #define VR_FRIENDLY_UNIT_DIED 3 #define VR_ONE_ENEMY_UNIT 4 #define VR_ALL_UNITS 5 class MPCtrl1 { I64 mode, lo, hi; Unit *tmpu; }; class MPCtrl2 { I64 lo, hi, row, col; }; U0 VRSetUp(I64 player) { I64 i; Unit *ut0, *ut1; ut0 = &units[player][0]; ut1 = &units[player ^ 1][0]; for (i = 0; i < UNITS_NUM; i++, ut0++, ut1++) { LBtr(&ut1->vis[player], 0); LBEqual(&ut0->vis[player], 0, ut0->life > 0); } } U0 VRMerge(I64 player) { I64 i, j; Unit *ut1; U8 *dst, *src, *mask = CAlloc((UNITS_NUM + 7) >> 3); for (j = 0; j < UNITS_NUM; j++) {//p0 src = &vis_unit_bitmap[player][(((UNITS_NUM + 7) & ~7)*j) >> 3]; dst = mask; for (i = 0; i < (UNITS_NUM + 7) >> 3; i++) //player1 *dst++ |= *src++; } ut1 = &units[player ^ 1][0]; for (j = 0; j < UNITS_NUM; j++, ut1++) LBEqual(&ut1->vis[player], 0, Bt(mask, j) && ut1->life > 0); Free(mask); } Bool MPVisRecalc(MPCtrl1 *job) { Bool res = FALSE, seen; I64 i, j, row, col; F64 x1, y1, x2, y2, dd, range; Unit *ut0, *ut1; ut0 = &units[cur_player][job->lo]; ut1 = &units[enemy_player][job->lo]; if (job->tmpu) { row = job->tmpu->row; col = job->tmpu->col; range = job->tmpu->range * 2 * HEX_RADIUS; range *= range; } switch (job->mode) { case VR_UPDATE_FRIENDLY_UNIT: case VR_ONE_FRIENDLY_UNIT: if (job->mode == VR_UPDATE_FRIENDLY_UNIT) range = F64_MAX; RowCol2XY(&x1, &y1, row, col); for (i = job->lo; i < job->hi; i++, ut1++) { seen = FALSE; if (ut1->life > 0 && LOS(row, col, ut1->row, ut1->col)) { RowCol2XY(&x2, &y2, ut1->row, ut1->col); dd = Sqr(x2 - x1) + Sqr(y2 - y1); if (dd < range) { seen = TRUE; LBts(&ut1->vis[cur_player], 0); } } if (job->mode == VR_UPDATE_FRIENDLY_UNIT) LBEqual(&vis_unit_bitmap[cur_player], i + job->tmpu->num * ((UNITS_NUM + 7) & ~7), seen); } break; case VR_ONE_ENEMY_UNIT: RowCol2XY(&x1, &y1, row, col); for (i = job->lo; i < job->hi; i++, ut1++) if (ut1->life > 0 && LOS(row, col, ut1->row, ut1->col)) { LBts(&vis_unit_bitmap[enemy_player], job->tmpu->num + i * ((UNITS_NUM + 7) & ~7)); res = TRUE; } else LBtr(&vis_unit_bitmap[enemy_player], job->tmpu->num + i * ((UNITS_NUM + 7) & ~7)); break; case VR_ALL_UNITS: ut0 = &units[cur_player][0]; for (i = 0; i < UNITS_NUM; i++, ut0++) if (ut0->life > 0) { RowCol2XY(&x1, &y1, ut0->row, ut0->col); ut1 = &units[enemy_player][job->lo]; for (j = job->lo; j < job->hi; j++, ut1++) { if (ut1->life > 0 && LOS(ut0->row, ut0->col, ut1->row, ut1->col)) { LBts(&ut1->vis[cur_player], 0); LBts(&vis_unit_bitmap[cur_player], j + i * ((UNITS_NUM + 7) & ~7)); } else LBtr(&vis_unit_bitmap[cur_player], j + i * ((UNITS_NUM + 7) & ~7)); } } else for (j = job->lo; j < job->hi ;j++) LBtr(&vis_unit_bitmap[cur_player], j + i * ((UNITS_NUM + 7) & ~7)); ut0 = &units[enemy_player][0]; for (i = 0; i < UNITS_NUM; i++, ut0++) if (ut0->life > 0) { RowCol2XY(&x1, &y1, ut0->row, ut0->col); ut1 = &units[cur_player][job->lo]; for (j = job->lo; j < job->hi; j++, ut1++) { if (ut1->life > 0 && LOS(ut0->row, ut0->col, ut1->row, ut1->col)) { LBts(&ut1->vis[enemy_player], 0); LBts(&vis_unit_bitmap[enemy_player], j + i * ((UNITS_NUM + 7) & ~7)); } else LBtr(&vis_unit_bitmap[enemy_player], j + i * ((UNITS_NUM + 7) & ~7)); } } else for (j = job->lo; j < job->hi; j++) LBtr(&vis_unit_bitmap[enemy_player], j + i * ((UNITS_NUM + 7) & ~7)); break; } return res; } Bool VisRecalc(I64 mode, Unit *tmpu=NULL) { I64 i, hi, k, count; Bool res; /* The compiler doesn't go out of it's way to know if something is const. ;-) This just compiles with the value at compile time, an advantage of just-in-time over AOT binaries. ZealOS has a limited stack size, so don't get in the habit. MAlloc() would probably be the better choice. */ MPCtrl1 job[mp_count]; CJob *cmd[mp_count]; if (mode == VR_FRIENDLY_UNIT_DIED) { MemSet((&vis_unit_bitmap[enemy_player])(U8 *) + (tmpu->num * ((UNITS_NUM + 7) & ~7)) >> 3, 0, (UNITS_NUM + 7) >> 3); VRMerge(enemy_player); return 0; //Return any value--don't care } count = mp_count; //Cores hi = UNITS_NUM; if (mode == VR_ONE_ENEMY_UNIT) { for (hi--; hi >= 0; hi--) if (units[enemy_player][hi].life > 0) break; hi++; } k = hi; if (hi / mp_count < 2) count = 1; for (i = 0; i < count; i++) { job[i].mode = mode; job[i].tmpu = tmpu; job[i].hi = k; k -= hi / count; if (k < 0) k = 0; if (i == count - 1) k = 0; job[i].lo = k; } res = FALSE; for (i = 0; i < count; i++) cmd[i] = JobQueue(&MPVisRecalc, &job[i], i, 0); for (i = 0; i < count; i++) if (JobResGet(cmd[i])) res = TRUE; if (mode == VR_UPDATE_FRIENDLY_UNIT) VRMerge(cur_player); return res; } U0 MPVisRecalcMap(MPCtrl2 *job) { I64 i, j; for (j = job->lo; j < job->hi; j++) for (i = 0; i < map_cols; i++) if (LOS(job->row, job->col, j, i)) vis_map[j][i] = TRUE; else vis_map[j][i] = FALSE; } U0 VisRecalcMap(I64 row, I64 col) { I64 i, hi, k, count; MPCtrl2 job[mp_count]; CJob *cmd[mp_count]; count = mp_count; //Cores hi = map_rows; k = hi; if (hi / mp_count < 2) count = 1; for (i = 0; i < count; i++) { job[i].row = row; job[i].col = col; job[i].hi = k; k -= hi/count; if (k < 0) k = 0; if (i == count - 1) k = 0; job[i].lo=k; } for (i = 0; i < count; i++) cmd[i] = JobQueue(&MPVisRecalcMap, &job[i], i, 0); for (i = 0; i < count; i++) JobResGet(cmd[i]); }