game_matrix01.py

#! /usr/bin/python3
# ==================================================================
# 3D Matrix Gane - Define Classes, etc,
# ==================================================================

import random

import game_matrix_config as cfg
import game_matrix_menu   as mnu


# ---- set the random number generator seed. -----------------------
# ---- this is to insure that during testing the the same ----------
# ---- random numbers will be generated ----------------------------

random.seed(a=101)


# ---- global data -------------------------------------------------
# CurrentNode  matrix current (working) node
# Debug        flag - print debug messages
# EndNode      matrix path end node
# MatrixEdge   nodes per matrix dimensions (x,y,z)
# StartNode    matrix path start node
# Verbose      flag - print verbose messages
# ------------------------------------------------------------------

global CurrentNode
global Debug
global EndNode
global MatrixEdge
global StartNode
global Verbose


# ---- matrix node class -------------------------------------------

class Node:
    '''
    The node at each cell in the 3D matrix.

    Attributes:
      x                 node's x coordinate
      y                 node's y coordinate
      z                 node's z coordinate
      up                y axis (y+1) adjacent node, if any
      down              y axis (y-1) adjacent node, if any
      forward           z axis (z+1) adjecent node, if any
      backward          z axis (z-1) adjecent node, if any
      left              x axis (x-1) adjecent node, if any
      right             x axis (x+1) adjecent node, if any
      wormhole          wormhole node, if any
      id                node's ID (integer)
    '''

    def __init__(self,x,y,z,id):
        '''
        Initialize a matrix node.
        '''
        self.x        = x
        self.y        = y
        self.z        = z
        self.up       = None
        self.down     = None
        self.forward  = None
        self.backward = None
        self.left     = None
        self.right    = None
        self.wormhole = None
        self.id       = id

    def get_id(self):
        '''
        Return a Node's id.
        '''
        return self.id

    def get_coords(self):
        '''
        Return a node's coordinates as a tuple (x,y,z).
        '''
        return (self.x,self.y,self.z)

    def get_nav_info(self):
        '''
        Return a node's navigation information as a list of tuples.

        The returned navigation tuples are (x,y,z) coordinates of the
        destination node or 'None' if there is no destination.

        The order of the list is
        [ up, down, forward, backward, left, right, wormhole ].
        '''
        navup       = \
            'None' if not self.up else self.up.get_coords()
        navdown     = \
            'None' if not self.down else self.down.get_coords()
        navforward  = \
            'None' if not self.forward else self.forward.get_coords()
        navbackward = \
            'None' if not self.backward else self.backward.get_coords()
        navleft     = \
            'None' if not self.left else self.left.get_coords()
        navright    = \
            'None' if not self.right else self.right.get_coords()
        navwormhole = \
            'None' if not self.wormhole else self.wormhole.get_coords()

        return [ navup,navdown,navforward,navbackward,navleft,
                 navright,navwormhole ]

    def set_up(self,node):
        '''
        Set the up link.
        '''
        self.up = node

    def set_down(self,node):
        '''
        Set the down link.
        '''
        self.down = node

    def set_forward(self,node):
        '''
        Set the forward link.
        '''
        self.forward = node

    def set_backward(self,node):
        '''
        Set the backward link.
        '''
        self.backward = node

    def set_left(self,node):
        '''
        Set the left link.
        '''
        self.left = node

    def set_right(self,node):
        '''
        Set the right link.
        '''
        self.right = node

    def set_wormhole(self,node):
        '''
        Set the wormhole link.
        '''
        self.wormhole = node

    def minimum_display(self):
        '''
        Display basic node information (x, y, z, and id)
        '''
        print('node: {},{},{} - {}'.
              format(self.x,self.y,self.z,self.id))


# ---- create_matrix

def create_matrix(mtrxedge,id=100):
    '''
    Return a matrix of unconnected nodes.

    (A cube mtrxedge by mtrxedge by mtrxedge)
    '''
    mtrx = []
    for x in range(0,mtrxedge):
        mtrx.append([])
        for y in range(0,mtrxedge):
            mtrx[x].append([])
            for z in range(0,mtrxedge):
                mtrx[x][y].append(Node(x,y,z,id))
                id += 1
    return mtrx


# ---- reset 3D matrix of nodes

def reset(mtrx,mtrxedge):
    '''
    Reset all of the matrix nodes movement links.
    (up, down, forward, backward, left, right, wormhole = None)
    '''
    for x in range(0,mtrxedge):
        for y in range(0,mtrxedge):
            for z in range(0,mtrixedge):
                mtrx[x][y][z].up       = None
                mtrx[x][y][z].down     = None
                mtrx[x][y][z].forward  = None
                mtrx[x][y][z].backward = None
                mtrx[x][y][z].left     = None
                mtrx[x][y][z].right    = None
                mtrx[x][y][z].wormhole = None


# ---- calculate the path start and end nodes

def start_end_nodes(mtrxedge):
    '''
    Calculate the coordinates of randomly selected
    start and end nodes for the path through the matrix.
    
    Return the coordinates as a tuple.
    (start_x,start_y,0,end_x,end_y,mtrxedge-1)

    Note the hard Z coordinate.
    '''
    sx = random.randrange(0,mtrxedge)     # start x
    sy = random.randrange(0,mtrxedge)     # start y
    ex = random.randrange(0,mtrxedge)     # end x
    ey = random.randrange(0,mtrxedge)     # end y
    return (sx,sy,0,ex,ey,mtrxedge-1)


# ---- display 3D matrix of nodes

def display_matrix(mtrx,mtrxedge):
    '''
    Display the minimum information about every
    node in the matrix.
    '''
    for x in range(0,mtrxedge):
        for y in range(0,mtrxedge):
            for z in range(0,mtrxedge):
                mtrx[x][y][z].minimum_display()

# ---- display a node's navigation information

def display_node_nav_info(node):
    '''
    Display a node's navigation information.

    Display:
        Available move directions
        Blocked move directions
        Wormhole available or not available
    '''
    print('\nCoords: x={},y={},z={}'.format(node.x,node.y,node.z))
    print('\nAvailable Move Directions:')
    if node.up:
        print('  up')
    if node.down:
        print('  down')
    if node.forward:
        print('  forward')
    if node.backward:
        print('  backward')
    if node.left:
        print('  left')
    if node.right:
        print('  right')
    print('\nBlocked Move Directions:')
    if not node.up:
        print('  up')
    if not node.down:
        print('  down')
    if not node.forward:
        print('  forward')
    if not node.backward:
        print('  backward')
    if not node.left:
        print('  left')
    if not node.right:
        print('  right')
    print('\nWormhole:')
    if node.wormhole:
        print('  available')
    else:
        print('  not available')

# ---- display matrix information

def display_matrix_info():
    '''
    Display matrix information.
    '''
    print('Current Node: {}'.format(
          'None' if not cfg.CurrentNode else
          cfg.CurrentNode.get_coords()))
    print('Start Node  : {}'.format(
          'None' if not cfg.StartNode else
          cfg.StartNode.get_coords()))
    print('End Node    : {}'.format(
          'None' if not cfg.EndNode
          else cfg.EndNode.get_coords()))
    print('MatrixEdge  : {}'.format(cfg.MatrixEdge))