#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#include<assert.h>
#include<chrono>
#include<random>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
#define SZ(x) ((int)x.size())
using namespace std;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
inline LL read()
{
	LL f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
template<typename T>inline void write(T x)
{
	if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
template<typename T>inline void pr1(T x){write(x);putchar(' ');}
template<typename T>inline void pr2(T x){write(x);putchar('\n');}
template<typename T>inline void chkmin(T &x,T y){x=x<y?x:y;}
template<typename T>inline void chkmax(T &x,T y){x=x>y?x:y;}
const int MAXN=1505;
const int mod=998244353;
int pow_mod(int a,int b)
{
	int ret=1;
	for(;b;b>>=1,a=1LL*a*a%mod)if(b&1)ret=1LL*ret*a%mod;
	return ret;	
}
char ch[MAXN][MAXN];int n;
char mp[MAXN][MAXN];
int dat[MAXN],vis[MAXN],cnt,ans;
vector<int> nxt[MAXN];
void ins(int x,int y){nxt[x].emplace_back(y);}
bool check(int x,int up)
{
	vis[x]=1;
	for(auto y:nxt[x])if(!vis[y])check(y,x);
	if(dat[x]&1)
	{
		if(!up)return false;
		dat[x]^=1;dat[up]^=1;
	}return true;
}
int solve(int N)
{
	++N;
	if(!(N&1))
	{
		int ret=0;
		for(int i=0;i<N;i++)for(int j=i+1;j<N;j++)ret+=mp[i][j]=='?';
		return pow_mod(2,ret);
	}
	memset(dat,0,sizeof(dat));for(int i=1;i<=N;i++)nxt[i].clear();
	int sum=0;
	for(int i=0;i<N;i++)
		for(int j=i+1;j<N;j++)
		{
			int u=i+1,v=j+1;
			if(mp[i][j]=='?')ins(u,v),ins(v,u),++sum;
			else if(mp[i][j]=='o')dat[u]^=1,dat[v]^=1;
		}
	memset(vis,0,sizeof(vis));bool flag=true;
	for(int i=1;i<=N;i++)if(!vis[i])
	{
		flag&=check(i,0);
		if(!flag)return 0;
		++sum;
	}--sum;sum-=(N-1);
	return pow_mod(2,sum);
}

int getxpos(int x,int y){return x+y;}
int getypos(int x,int y){return 0+(y-x);}

int main()
{
	n=read()-1;for(int i=1;i<=n;i++)scanf("%s",ch[i]+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(ch[i][j]!='?')
	{
		if(ch[j][i]!='?'&&ch[j][i]!=ch[i][j])return pr2(0),0;
		ch[j][i]=ch[i][j];
	}
	for(int i=1;i<=n;i++)reverse(ch[i]+1,ch[i]+1+n);
	for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(ch[i][j]!='?')
	{
		if(ch[j][i]!='?'&&ch[j][i]!=ch[i][j])return pr2(0),0;
		ch[j][i]=ch[i][j];
	}ans=1;
	for(int i=1;i<=n-i+1;i++)
		for(int j=i;j<=n-i+1;j++)if(!((i+j)&1))
		{
			chkmax(cnt,getxpos(i,j)>>1);chkmax(cnt,getypos(i,j)>>1);
			mp[getxpos(i,j)>>1][getypos(i,j)>>1]=mp[getypos(i,j)>>1][getxpos(i,j)>>1]=ch[i][j];
		}
	ans=1LL*ans*solve(cnt)%mod;
	cnt=0;
	for(int i=1;i<=n-i+1;i++)
		for(int j=i;j<=n-i+1;j++)if(((i+j)&1))
		{
			chkmax(cnt,getxpos(i,j)>>1);chkmax(cnt,getypos(i,j)>>1);
			mp[getxpos(i,j)>>1][getypos(i,j)>>1]=mp[getypos(i,j)>>1][getxpos(i,j)>>1]=ch[i][j];
		}
	ans=1LL*ans*solve(cnt)%mod;
	pr2(ans);
	return 0;
}

Measured memory_bytes: 7040