scummvm/engines/chewy/movclass.cpp
Filippos Karapetis 2f00e8d279 CHEWY: Rename ged to barriers
Makes it a bit clearer to understand its purpose
2022-05-22 17:29:57 +03:00

788 lines
19 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "chewy/movclass.h"
#include "chewy/defines.h"
#include "chewy/globals.h"
namespace Chewy {
#define LEFT_VECT -1
#define RIGHT_VECT 1
#define MOV_START 0
#define MOV_FOUND 1
#define MOV_UNPASSABLE 2
#define Y_DOWN 1
#define Y_UP 2
#define SOURCE_COL 14
#define DEST_COL 19
#define CHECK_COL 255
#define MIN_COL 8
#define UNBEGEHBAR_COL 3
#define CONNECT_COL 15
#define CUR_COL 13
#define S_OBEN 0
#define S_RECHTS 1
#define S_UNTEN 2
#define S_LINKS 3
#define MOV_X 1
#define MOV_Y 2
MovClass::MovClass() {
_vecTbl[0] = -40;
_vecTbl[1] = 1;
_vecTbl[2] = 40;
_vecTbl[3] = -1;
}
MovClass::~MovClass() {
}
void MovClass::goto_xy(GotoPkt *gp) {
const int16 width = _G(room)->_barriers->getWidth();
_gpkt = gp;
_agv.AutoGo = false;
_agv.Continue = false;
_vecTbl[0] = -width;
_vecTbl[2] = width;
_plotDelay = 20;
calc_xy();
_plotDelay = 0;
int16 start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
int16 ziel_feld = get_feld_nr(_gpkt->Dx, _gpkt->Dy);
int16 tmp = ziel_feld;
calc_go(start_feld, &ziel_feld);
if (tmp != ziel_feld) {
get_mov_line();
if (_gml.MLineFeld != -1) {
calc_mov_line_xit(_gml.MLineFeld);
if (_mle.FNr != -1) {
_agv.AutoGo = true;
_agv.Start = 0;
_agv.LastFeld = -1;
_agv.AkKnoten = 0;
start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
ziel_feld = _gml.MLineFeld;
calc_go(start_feld, &ziel_feld);
if (_gml.MLineFeld != ziel_feld) {
_agv.PktAnz = 2;
} else {
_agv.PktAnz = 1;
}
}
}
}
}
int16 MovClass::calc_auto_go(int16 x, int16 y, int16 *auto_x, int16 *auto_y) {
int16 ret = -1;
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
if (_agv.AutoGo == true) {
const byte *data = _G(room)->_barriers->getData();
const byte *buffer = data + 6;
buffer += (width * height) * _gpkt->AkMovEbene;
if (!_agv.Start) {
_agv.Start = _agv.PktAnz;
if (_agv.PktAnz == 1) {
_agv.Start = 3;
get_feld_xy(_gml.MLineFeld, &_agv.X_End, &_agv.Y_End);
_agv.AkFeld = _gml.MLineFeld;
} else {
get_feld_xy(_gml.GotoFeld, &_agv.X_End, &_agv.Y_End);
_agv.AkFeld = _gml.GotoFeld;
}
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else {
if (get_feld_nr(x, y) == _agv.AkFeld) {
if (_agv.Start == 2) {
_agv.Start = 3;
get_feld_xy(_gml.GotoFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else if (_agv.Start == 3) {
if (_agv.LastFeld == -1) {
_agv.LastFeld = _gml.MLineFeld;
_agv.AkFeld = _gml.MLineFeld + _mle.Direction;
if (buffer[_agv.AkFeld] == MOV_LINE_KNOTEN) {
_feld1knoten = true;
} else
_feld1knoten = false;
get_feld_xy(_agv.AkFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
ret = true;
} else if (get_feld_nr(x, y) == _agv.AkFeld) {
if (_agv.AkFeld == _mle.FNr) {
_agv.AutoGo = false;
*auto_x = _gpkt->Dx;
*auto_y = _gpkt->Dy;
ret = true;
} else {
int16 ok = 0;
if (_feld1knoten) {
_feld1knoten = false;
_agv.LastFeld = _agv.AkFeld;
_agv.AkFeld = _mle.KnPkt[_agv.AkKnoten];
++_agv.AkKnoten;
if (_agv.AkFeld != -1)
ok = 1;
} else {
for (int16 i = 0; i < 4 && !ok; i++) {
if (buffer[_agv.AkFeld + _vecTbl[i]] == MOV_LINE_IDX) {
if (_agv.AkFeld + _vecTbl[i] != _agv.LastFeld) {
_agv.LastFeld = _agv.AkFeld;
_agv.AkFeld += _vecTbl[i];
ok = 1;
}
} else if (buffer[_agv.AkFeld + _vecTbl[i]] == MOV_LINE_KNOTEN) {
if (_agv.AkFeld + _vecTbl[i] != _agv.LastFeld) {
_agv.LastFeld = _agv.AkFeld + _vecTbl[i];
_agv.AkFeld = _mle.KnPkt[_agv.AkKnoten];
++_agv.AkKnoten;
if (_agv.AkFeld == -1)
ok = 0;
else
ok = 1;
}
}
}
}
if (ok) {
get_feld_xy(_agv.AkFeld, &_agv.X_End, &_agv.Y_End);
*auto_x = _agv.X_End + 4;
*auto_y = _agv.Y_End + 4;
} else {
_agv.AutoGo = false;
*auto_x = _gpkt->Dx;
*auto_y = _gpkt->Dy;
}
ret = true;
}
}
}
}
}
delete[] data;
}
return ret;
}
void MovClass::stop_auto_go() {
_agv.AutoGo = false;
_agv.Continue = true;
}
void MovClass::continue_auto_go() {
_agv.AutoGo = _agv.Continue;
}
bool MovClass::auto_go_status() {
return _agv.AutoGo;
}
void MovClass::calc_xy() {
int16 xvector = 0;
int16 yvector = 0;
if (!_G(barriers)->getBarrierId(_gpkt->Dx, _gpkt->Dy)) {
int16 ende = 0;
int16 count = 0;
int16 min_x = -1;
int16 min_y = -1;
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
while (!ende) {
int16 min_steps = 30000;
int16 x = _gpkt->Dx - (count + 1) * 8;
int16 y = _gpkt->Dy - (count + 1) * 8;
for (int16 seite = 0; seite < 4; seite++) {
int16 anz = 2 + (count * 2);
switch (seite) {
case S_OBEN:
xvector = 8;
yvector = 0;
break;
case S_RECHTS:
xvector = 0;
yvector = 8;
break;
case S_UNTEN:
xvector = -8;
yvector = 0;
break;
case S_LINKS:
xvector = 0;
yvector = -8;
break;
default:
break;
}
for (int16 i = 0; i < anz; i++) {
if (x >= 0 && x < width * 8 &&
y >= 0 && y < height * 8) {
if (_G(barriers)->getBarrierId(x, y)) {
int16 aksteps = abs(_gpkt->Dx - x);
aksteps += abs(_gpkt->Dy - y);
if (aksteps < min_steps) {
min_steps = aksteps;
min_x = x;
min_y = y;
}
}
}
x += xvector;
y += yvector;
}
}
++count;
if (min_steps != 30000) {
ende = 1;
int16 tmp_feld = get_feld_nr(min_x, min_y);
get_feld_xy(tmp_feld, &_gpkt->Dx, &_gpkt->Dy);
_gpkt->Dx += 4;
_gpkt->Dy += 4;
}
}
}
}
short MovClass::calc_go(int16 src_feld, int16 *dst_feld) {
int16 new_vector = true;
ObjMov om;
MovInfo mi;
mi.Vorschub = _gpkt->Vorschub;
get_feld_xy(src_feld, &om.Xypos[0], &om.Xypos[1]);
get_feld_xy(*dst_feld, &mi.XyzEnd[0], &mi.XyzEnd[1]);
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
bool endFl = false;
int16 mov_ok = 0;
int16 steps = 0;
int16 abbruch = MOV_START;
while (!endFl && !abbruch) {
if (om.Count > 0) {
--om.Count;
int16 tmpx = om.Xyvo[0];
int16 tmpy = om.Xyvo[1];
int16 tmpz = om.Xyvo[2];
om.Xyna[0][0] += om.Xyna[0][1];
if (om.Xyna[0][1] < 0) {
if (om.Xyna[0][0] < -1000) {
om.Xyna[0][0] += 1000;
--tmpx;
}
} else if (om.Xyna[0][0] > 1000) {
om.Xyna[0][0] -= 1000;
++tmpx;
}
om.Xyna[1][0] += om.Xyna[1][1];
if (om.Xyna[1][1] < 0) {
if (om.Xyna[1][0] < -1000) {
om.Xyna[1][0] += 1000;
--tmpy;
}
} else if (om.Xyna[1][0] > 1000) {
om.Xyna[1][0] -= 1000;
++tmpy;
}
om.Xyna[2][0] += om.Xyna[2][1];
if (om.Xyna[2][1] < 0) {
if (om.Xyna[2][0] < -1000) {
om.Xyna[2][0] += 1000;
}
} else if (om.Xyna[2][0] > 1000) {
om.Xyna[2][0] -= 1000;
}
tmpz = 0;
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpx + tmpz,
om.Xypos[1] + tmpy + tmpz)) {
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpx + tmpz,
om.Xypos[1] + tmpz)) {
if (!_G(barriers)->getBarrierId(om.Xypos[0] + tmpz,
om.Xypos[1] + tmpy + tmpz)) {
abbruch = MOV_UNPASSABLE;
} else {
if (!tmpy) {
abbruch = MOV_UNPASSABLE;
} else if (abs(om.Xypos[1] - mi.XyzEnd[1]) <= abs(tmpy)) {
abbruch = MOV_FOUND;
} else {
mov_ok = MOV_Y;
}
}
} else {
if (!tmpx) {
abbruch = MOV_UNPASSABLE;
} else if (abs(om.Xypos[0] - mi.XyzEnd[0]) <= abs(tmpx)) {
abbruch = MOV_FOUND;
} else {
mov_ok = MOV_X;
}
}
} else {
++steps;
om.Xypos[0] += tmpx;
om.Xypos[1] += tmpy;
om.Xypos[2] += tmpz;
if (new_vector) {
new_vector = false;
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
}
if (om.Count == 0) {
abbruch = MOV_FOUND;
}
}
if (mov_ok) {
++steps;
if (mov_ok == MOV_X)
om.Xypos[0] += tmpx;
else
om.Xypos[1] += tmpy;
om.Xypos[2] += tmpz;
mi.XyzStart[0] = om.Xypos[0];
mi.XyzStart[1] = om.Xypos[1];
get_mov_vector(mi.XyzStart, mi.XyzEnd, mi.Vorschub, &om);
if (mov_ok == MOV_X) {
if (om.Xyvo[0] != 0)
new_vector = true;
} else {
if (om.Xyvo[1] != 0)
new_vector = true;
}
if (om.Count == 0) {
abbruch = MOV_FOUND;
}
mov_ok = false;
}
} else
endFl = true;
}
if (abbruch == MOV_UNPASSABLE)
*dst_feld = get_feld_nr(om.Xypos[0], om.Xypos[1]);
return steps;
}
void MovClass::get_mov_line() {
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
const int16 level = _G(room)->_barriers->getLevel();
const byte *data = _G(room)->_barriers->getData();
const byte *buffer = data + 6;
int16 ak_steps;
_gml.GotoFeld = -1;
_gml.MLineFeld = -1;
if (level > 1) {
buffer += (width * height) * _gpkt->AkMovEbene;
int16 start_feld = get_feld_nr(_gpkt->Sx, _gpkt->Sy);
int16 ende = 0;
int16 count = 0;
int16 min_steps = 30000;
int16 count_vect = width;
int16 y_richtung = Y_DOWN;
while (!ende) {
int16 tmp_feld = start_feld + count * count_vect;
if (_G(barriers)->getBarrierId(tmp_feld, data + 6)) {
int16 abbruch = 0;
int16 vector = 0;
while ((tmp_feld % width) < (width - 1) && !abbruch)
{
if (_G(barriers)->getBarrierId(tmp_feld + vector, data + 6)) {
tmp_feld += vector;
if (buffer[tmp_feld] == MOV_LINE_IDX) {
ak_steps = abs((tmp_feld % width) - (start_feld % width));
ak_steps += abs((tmp_feld / width) - (start_feld / width));
if (ak_steps < min_steps) {
min_steps = ak_steps;
_gml.GotoFeld = start_feld + count * count_vect;
_gml.MLineFeld = tmp_feld;
}
}
vector = RIGHT_VECT;
} else {
abbruch = MOV_UNPASSABLE;
}
}
tmp_feld = start_feld + count * count_vect;
vector = LEFT_VECT;
abbruch = 0;
while ((tmp_feld % width) > 0 && !abbruch) {
if (_G(barriers)->getBarrierId(tmp_feld + vector, data + 6)) {
tmp_feld += vector;
if (buffer[tmp_feld] == MOV_LINE_IDX) {
ak_steps = abs((tmp_feld % width) - (start_feld % width));
ak_steps += abs((tmp_feld / width) - (start_feld / width));
if (ak_steps < min_steps) {
min_steps = ak_steps;
_gml.GotoFeld = start_feld + count * count_vect;
_gml.MLineFeld = tmp_feld;
}
}
} else {
abbruch = MOV_UNPASSABLE;
}
}
++count;
} else {
if (y_richtung == Y_DOWN) {
y_richtung = Y_UP;
count = 1;
count_vect = -_G(room)->_barriers->getWidth();
} else
ende = 1;
}
}
}
delete[] data;
}
void MovClass::calc_mov_line_xit(int16 start_feld) {
const int16 width = _G(room)->_barriers->getWidth();
const int16 height = _G(room)->_barriers->getHeight();
const int16 level = _G(room)->_barriers->getLevel();
const byte *data = _G(room)->_barriers->getData();
int16 tmp_feld;
int16 i;
int16 dest_steps;
int16 k;
int16 TmpKnPkt[MAX_KNOTEN_PKT];
int16 dir_unerreicht = 0;
int16 KnPkt_unrreicht[MAX_KNOTEN_PKT];
int16 feld_unerreicht = 0;
int16 knoten_felder[MAX_KNOTEN_PKT][6];
for (i = 0; i < MAX_KNOTEN_PKT; i++)
TmpKnPkt[i] = -1;
if (level > 1) {
memset(knoten_felder, -1, MAX_KNOTEN_PKT * 6);
const byte *buffer = data + 6;
buffer += (width * height) * _gpkt->AkMovEbene;
_mle.Steps = 30000;
int16 min_step_unerreicht = 30000;
_mle.FNr = -1;
int16 ziel_feld = get_feld_nr(_gpkt->Dx, _gpkt->Dy);
int16 calc_feld = start_feld;
int16 last_feld = start_feld;
int16 steps = 0;
int16 found = 0;
int16 ak_knoten = -1;
int16 tbl_dir = 1;
int16 tbl_ptr = 0;
int16 knoten_flag = 0;
//found_min = 0;
int16 dir = 30000;
while (!found) {
tmp_feld = ziel_feld;
calc_go(calc_feld, &tmp_feld);
if (tmp_feld == ziel_feld) {
dest_steps = abs((ziel_feld % width) - (calc_feld % width));
dest_steps += abs((ziel_feld / width) - (calc_feld / width));
if (dest_steps < _mle.Steps) {
_mle.Steps = dest_steps;
_mle.FNr = calc_feld;
if (dir == 30000)
_mle.Direction = 0;
else
_mle.Direction = dir;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
_mle.KnPkt[i] = TmpKnPkt[i];
}
} else {
dest_steps = abs((ziel_feld % width) - (tmp_feld % width));
dest_steps += abs((ziel_feld / width) - (tmp_feld / width));
if (dest_steps < min_step_unerreicht) {
min_step_unerreicht = dest_steps;
feld_unerreicht = tmp_feld;
if (dir == 30000)
dir_unerreicht = 0;
else
dir_unerreicht = dir;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
KnPkt_unrreicht[i] = TmpKnPkt[i];
}
}
int16 ok = 0;
for (i = 0; i < 4 && !ok; i++) {
if (buffer[calc_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_IDX)
{
if (calc_feld + _vecTbl[tbl_ptr + i * tbl_dir] != last_feld)
{
last_feld = calc_feld;
calc_feld += _vecTbl[tbl_ptr + i * tbl_dir];
++steps;
ok = 1;
if (dir == 30000) {
dir = _vecTbl[tbl_ptr + i * tbl_dir];
}
if (knoten_flag) {
TmpKnPkt[ak_knoten] = calc_feld;
knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] = calc_feld;
knoten_flag = false;
}
}
} else if (buffer[calc_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_KNOTEN) {
if (calc_feld + _vecTbl[tbl_ptr + i * tbl_dir] != last_feld) {
if (dir == 30000) {
dir = _vecTbl[tbl_ptr + i * tbl_dir];
}
++ak_knoten;
for (k = 0; k < 6; k++)
knoten_felder[ak_knoten][k] = -1;
switch (tbl_ptr + i * tbl_dir) {
case MLE_UP:
k = MLE_DOWN;
break;
case MLE_RIGHT:
k = MLE_LEFT;
break;
case MLE_LEFT:
k = MLE_RIGHT;
break;
case MLE_DOWN:
k = MLE_UP;
break;
}
knoten_felder[ak_knoten][k] = calc_feld;
last_feld = calc_feld;
calc_feld += _vecTbl[tbl_ptr + i * tbl_dir];
knoten_felder[ak_knoten][4] = calc_feld;
++steps;
knoten_felder[ak_knoten][5] = steps;
knoten_flag = true;
ok = 1;
}
}
}
if (!ok) {
if (ak_knoten != -1)
{
ok = 0;
for (i = 0; i < 4 && !ok; i++) {
if (knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] == -1) {
tmp_feld = knoten_felder[ak_knoten][4];
if (buffer[tmp_feld + _vecTbl[tbl_ptr + i * tbl_dir]] == MOV_LINE_IDX)
{
last_feld = knoten_felder[ak_knoten][4];
calc_feld = tmp_feld + _vecTbl[tbl_ptr + i * tbl_dir];
TmpKnPkt[ak_knoten] = calc_feld;
knoten_felder[ak_knoten][tbl_ptr + i * tbl_dir] = calc_feld;
steps = knoten_felder[ak_knoten][5];
ok = 1;
}
}
}
if (!ok) {
--ak_knoten;
}
} else if (tbl_dir == 1) {
tbl_dir = -1;
tbl_ptr = 3;
dir = 30000;
//found_min = 0;
calc_feld = start_feld;
last_feld = start_feld;
} else {
found = 1;
if (_mle.FNr == -1) {
_mle.Steps = min_step_unerreicht;
_mle.FNr = feld_unerreicht;
_mle.Direction = dir_unerreicht;
for (i = 0; i < MAX_KNOTEN_PKT; i++)
_mle.KnPkt[i] = KnPkt_unrreicht[i];
get_feld_xy(feld_unerreicht, &_gpkt->Dx, &_gpkt->Dy);
_gpkt->Dx += 4;
_gpkt->Dy += 4;
}
}
}
}
}
delete[] data;
}
int16 MovClass::get_feld_nr(int16 x, int16 y) {
const int16 width = _G(room)->_barriers->getWidth();
x >>= 3;
y >>= 3;
return x + (y * width);
}
void MovClass::get_feld_xy(int16 fnr, int16 *x, int16 *y) {
const int16 width = _G(room)->_barriers->getWidth();
*x = (fnr % width);
*y = (fnr / width);
*x <<= 3;
*y <<= 3;
}
void MovClass::get_mov_vector(int16 *startXyz, int16 *endXyz, int16 vorschub, ObjMov *om) {
if (vorschub > 0) {
int16 x = startXyz[0];
int16 y = startXyz[1];
int16 z = startXyz[2];
int16 x1 = endXyz[0];
int16 y1 = endXyz[1];
int16 z1 = endXyz[2];
om->Xypos[0] = x;
om->Xypos[1] = y;
om->Xypos[2] = z;
x = x - x1;
y = y - y1;
z = z - z1;
uint8 xvector;
if (x < 0) {
xvector = 1;
--x;
} else {
xvector = 0;
++x;
}
uint8 yvector;
if (y < 0) {
yvector = 1;
--y;
} else {
yvector = 0;
++y;
}
uint8 zvector;
if (z < 0) {
zvector = 1;
--z;
} else {
zvector = 0;
++z;
}
int16 absx = abs(x);
int16 absy = abs(y);
int16 absz = abs(z);
float xstep;
float ystep;
if (absx < absy) {
xstep = (float)absx / ((float)absy / (float)vorschub);
ystep = vorschub;
om->Count = (int16)((float) y / (float)ystep);
} else {
xstep = vorschub;
ystep = (float)absy / ((float)absx / (float)vorschub);
om->Count = (int16)((float) x / (float)xstep);
}
float zstep;
om->Count = abs(om->Count);
if (!om->Count) {
zstep = (float)absz / 1.0;
} else
zstep = (float)absz / ((float)((abs)(om->Count)));
if (!xvector)
xstep = -xstep;
if (!yvector)
ystep = -ystep;
if (!zvector)
zstep = -zstep;
om->Xyvo[0] = (int16)xstep;
om->Xyvo[1] = (int16)ystep;
om->Xyvo[2] = (int16)zstep;
int16 tmp = (int16)((float)xstep * 1000.0);
om->Xyna[0][1] = tmp - (om->Xyvo[0] * 1000);
om->Xyna[0][0] = 0;
tmp = (int16)((float)ystep * 1000.0);
om->Xyna[1][1] = tmp - (om->Xyvo[1] * 1000);
om->Xyna[1][0] = 0;
tmp = (int16)((float)zstep * 1000.0);
om->Xyna[2][1] = tmp - (om->Xyvo[2] * 1000);
om->Xyna[2][0] = 0;
if (!om->Count) {
startXyz[0] = endXyz[0];
startXyz[1] = endXyz[1];
om->Xypos[0] = endXyz[0];
om->Xypos[1] = endXyz[1];
}
} else {
om->Count = 0;
om->Xypos[0] = startXyz[0];
om->Xypos[1] = startXyz[1];
om->Xypos[2] = startXyz[2];
om->Xyvo[0] = 0;
om->Xyvo[1] = 0;
om->Xyvo[2] = 0;
om->Xyna[0][1] = 0;
om->Xyna[0][0] = 0;
om->Xyna[1][1] = 0;
om->Xyna[1][0] = 0;
om->Xyna[2][1] = 0;
om->Xyna[2][0] = 0;
}
}
} // namespace Chewy