Trouble building tree for possible chess piece movements - ruby

I'm building a chess game that takes a start coordinate and end coordinate and builds a tree using BFS. I have two methods to find possible moves.
The #find_possible_positions_from_origin method logs every single possible square that chess piece can end up (for example a rook can end up either, north up to 7 spaces, south up to 7 spaces, left up to 7 spaces, and right up to 7 spaces. If the end coordinate ends up BEING one of these coordinates from #find_possible_positions_from_origin, it then runs another method directly under it #find_possible_incremental_moves that traverses every single one of these spaces by only 1 space at a time - the reason being so that it can check if each space is empty, and not just hop over another piece. It creates a "cell" on each of these spaces so that it can log the path to destination. Each cell remembers the path to it from the starting coordinate.
I'm having trouble getting the second variable #find_possible_incremental_moves run smoothly under the #find_possible_positions_from_origin method. A "cell" is supposed to be created at the destination coordinate of the board, so that I can have the path to it, and check if the path is occupied by any other pieces. But when I call the destination coordinate, I get nil.
Someone corrected me on a previous question that I shouldn't post my entire production code which makes sense, so I included the single #build_tree that I'm having trouble with I hope that's enough.
Here is my code that have for this section.
def build_tree
#start_coor = convert_input_to_coor(#start)
#destination_coor = convert_input_to_coor(#destination)
#selected_piece = #gameboard[#start_coor[0]][#start_coor[1]]
starting_cell = Cell.new(#start_coor[0], #start_coor[1])
queue = []
queue.unshift(starting_cell)
until queue.empty?
current = queue.shift
possible_positions = find_possible_positions_from_origin([current.x, current.y])
next if possible_positions.nil?
if possible_positions.include?(#destination_coor)
#selected_piece.possible_positions = find_possible_incremental_moves(([current.x, current.y]))
#selected_piece.possible_positions.each do |move|
next unless !#dummyboard.board[move[0]][move[1]].instance_of? Cell
linked_cell = Cell.new(move[0], move[1])
current.edges << linked_cell
linked_cell.path = current.path + linked_cell.path
#dummyboard.board[move[0]][move[1]] = linked_cell
queue.push(linked_cell)
end
end
end
starting_cell
end

Related

Create Buttons and it's signals dynamically in Ruby GTK

i'm trying to make a Nurikabe puzzle with Ruby GTK and i'm having trouble creating button signals dynamically.
Basically, i have a matrix, some boxes have a number ( clicking them won't do anything), others can have one of 3 states (white, black or unplayed). The matrix can have different sizes so i did this :
def construction
# we get the width and height of the matrix
taille_hauteur = ##partie.grilleEnCours.hauteur
taille_largeur = ##partie.grilleEnCours.largeur
#boutons = {}
#We create a table which will include all of our buttons (one for each box of our matrix)
table = Table.new(taille_hauteur,taille_largeur,false)
# we go through our matrix
for i in 0..taille_largeur-1
for j in 0..taille_hauteur-1
# if the box has a number, we create a button with that number as a label
if ##partie.grilleEnCours.matriceCases[i][j].is_a?(CaseNombre)
# we add this button to a hash
#boutons[[i,j]] = Button.new(:label=> ##partie.grilleEnCours.matriceCases[i][j].to_s)
table.attach(#boutons[[i,j]], i, i+1, j, j+1)
else
# otherwise,we create and add a button to the hash without a label
#boutons[[i,j]] = Button.new()
# we create a signal, changing the state of the box of the matrix at the same coordinates as the button
#boutons[[i,j]].signal_connect('clicked'){
puts "#{i} #{j}"
# we change the box's state of the matrix
##partie.clicSurCase(i,j)
puts ##partie.grilleEnCours
# here we are just changing the label corresponding to the box's state
if(##partie.grilleEnCours.matriceCases[i][j].etat==0)
lab = ""
elsif (##partie.grilleEnCours.matriceCases[i][j].etat==1)
lab = "Noir"
else
lab = "Point"
end
#boutons[[i,j]].set_label(lab)
}
table.attach(#boutons[[i,j]], i, i+1, j, j+1)
end
end
end
#object.add(table)
end
The problem is, doing this, when we click any button, it will change the last box of the matrix and the last button's label (bottom right). I believe this is because Integers are objects in Ruby so clicking a button will change the box's state and button's state at the coordinates (i,j) (which are matrix height-1, matrix width-1) and not the values i and j had when we created the signal.
I have no idea how to link a button to a specific box of the matrix (knowing matrixes can have multiple sizes), could you help me on this one ?
It is quite hard to read such a large block of code - maybe start by chopping it into logic-based functions?
It will clear the code up.
you don't need to set "lab =" in each branch of if - just:
lab = if (i==1)
1
else
2
end
in additions - use "case" in this case. Once you split the code up - you will(probably) find the issue you have.
it will be easier to debbug.

How do I make a script affect all its children in Roblox LUA?

I'm new to programming in LUA, although I've learned similar languages like JS. It's frustrating if I have to alter the same script in many parts in a group by replacing each script, and I don't know of an elegant way to do it. Instead, I decided to nest all the parts inside of the script. I've seen some examples and I've tried to adapt some of them, but they don't exactly apply to what I want to do and I can't get them to work.
In essence, what I'm trying to do is monitor all the bricks for a player to contact them. I took the original disappearing brick script that was nested inside each brick and modified it. If a part (brick) is touched, that should call the onTouch function, which will make the brick's transparency decrease over time until the in pairs loop is done, after which the brick disappears and CanCollide is turned off. After 2 seconds, it then returns back to normal. I think the problem is with the coding I used to monitor the parts as I don't really understand the right way to monitor multiple objects. Can someone please help? Thanks!
File structure:
function onTouched(brick)
local delay = .1 -- the delay between each increase in transparency (affects speed of disappearance)
local RestoreDelay = 2 -- delay before the brick reappears
local inc = .1 -- how much the brick disappears each time
-- All characters have a Humanoid object
-- if the model has one, it is a character
local h = script.Child:findFirstChild("Humanoid") -- Find Humanoids in whatever touched this
if (h ~=nil) then -- If there is a Humanoid then
h.Health = h.MaxHealth -- Set the health to maximum (full healing)
for x=0,1, inc do
script.Child.Transparency = x+inc
script.Child.CanCollide = true
wait(delay)
end
wait(delay)
script.Child.Transparency = 1
script.Child.CanCollide = false
wait(RestoreDelay)
script.Child.Transparency = 0
script.Child.CanCollide = true
else
end
end
while true do
local bricks=script:GetChildren():IsA("basic.part")
for x=1,brick in pairs(bricks) do
brick.Touched:connect(onTouched(brick)) -- Make it call onTouched when touched
end
end
end
For the most part, you've gotten it right, but you've got a few syntax errors where there are different conventions between JavaScript and Lua.
In JS, you would fetch an array of objects and then bee able to filter it immediately, but in Lua, there is limited support for that. So a JavaScript line like :
var bricks = script.GetChildren().filter(function(item) {
return item === "basic.part"
})
cannot be done all in one line in Lua without assistance from some library. So you'll need to move the check into the loop as you iterate over the objects.
Other than that, the only other thing to change is the onTouched handler's function signature. The BasePart.Touched event tells you which object has touched the brick, not the brick itself. But by creating a higher order function, it's easy to get access to the brick, and the thing that touched it.
-- create a helper function to access the brick and the thing that touched it
function createOnTouched(brick)
-- keep track whether the animation is running
local isFading = false
return function(otherPart)
-- do not do the animation again if it has already started
if isFading then
return
end
local delay = .1 -- the delay between each increase in transparency (affects speed of disappearance)
local restoreDelay = 2 -- delay before the brick reappears
local inc = .1 -- how much the brick disappears each time
-- All characters have a Humanoid object, check for one
local h = otherPart.Parent:FindFirstChild("Humanoid")
if h then
-- heal the player
h.Health = h.MaxHealth
-- start fading the brick
isFading = true
brick.CanCollide = true
for i = 0, 1, inc do
brick.Transparency = i
wait(delay)
end
-- turn off collision for the brick
wait(delay)
brick.Transparency = 1
brick.Anchored = true
brick.CanCollide = false
-- turn the part back on
wait(restoreDelay)
brick.Transparency = 0
brick.CanCollide = true
-- reset the animation flag
isFading = false
end
end
end
-- loop over the children and connect touch events
local bricks = script:GetChildren()
for i, brick in ipairs(bricks) do
if brick:IsA("BasePart") then
local onTouchedFunc = createOnTouched(brick)
brick.Touched:Connect(onTouchedFunc)
end
end

Dividing by half in ruby to create an effective calculator

For the past while I've been working on a calculator, but have run into problems when needing to divide by a half. I'll add the offending bit of code along with a loop to keep it open below.
on = true
while on == true do
half = 1.0 / 2.0
puts ("FUNCTION IN TESTING MODE, DO NOT EXPECT IT TO FUNCTION PROPERLY")
puts ("Area of a triangle")
print("What is the legnth of the base? ").to_i
base = gets.chomp("base")
print("\nWhat is the height? ")
height = gets.chomp("height").to_i
PreAreaT = base * height
AreaT = PreAreaT * half
puts("The area of the triangle is #{AreaT}")
end
So essentially, how on Earth do I get the program to display an answer, rather than outputting nothing for the answer?
EDIT:As it would turn out the code above is improperly done. I've spent nearly two weeks asking myself why it wouldn't work only to find I had .to_i after a print statement rather than the input.
Your to_i call is switched around here.
print("What is the legnth of the base? ").to_i
base = gets.chomp("base")
Should be the other way 'round.
print("What is the length of the base? ")
base = gets.chomp("base").to_i
Further, chomp will attempt to remove any occurrences of base or height from the string. Be sure that you're intention is to remove those occurrences; if you want to remove whitespace, you'll have to take a different approach.

How to keep panning only if id exists?

I'm trying to pan through a list of elements to confirm that the set minimum number of elements is there on the screen. The problem I'm running into is that 'pan' will keep going and the test will pass even if I set the minimum to a high number (greater than what's actually there on the page).
When /^I swipe through my list of chat suggestion cards I should see the minimum$/ do
i = 0
while i < 12
i += 1
wait_for_element_exists("* id:'itemContainer'")
pan("* id:'itemContainer'", :left)
end
end
Is there anyway to check if the number of id: 'itemContainer' is actually there, to make it fail if the minimum number doesn't exist?
Query will only return the elements that are currently on the screen, so you will have to swipe across to make all of the cards visible to calabash and check for them. Assuming that query("* id:'itemContainer'") would only find one at a time, i.e. the cards are a whole screen in size,
12.times do
card_before_panning = query("* id:'itemContainer'")
pan("* id:'itemContainer'", :left)
card_after_panning = query("* id:'itemContainer'")
assert_not_equal card_before_panning, card_after_panning
end
If more than one of the cards can be visible on the screen at a time then you will have to do an additional check. Assuming that there could be two visible at the time
11.times do
card_before_panning = query("* id:'itemContainer' index:0")
pan("* id:'itemContainer'", :left)
card_after_panning = query("* id:'itemContainer' index:0")
assert_not_equal card_before_panning, card_after_panning
end
# Then check that there are two visible on the final screen.
assert_equal 2, query("* id:'itemContainer'").size
Note that this will only work if the cards appear differently in your app, i.e. they have different content. If query("* id:'itemContainer'") has identical results for each of the cards then calabash will not be able to tell them apart to see if anything has changed.

psychopy polygon on top of image

using psychopy ver 1.81.03 on a mac I want to draw a polygon (e.g. a triangle) on top of an image.
So far, my image stays always on top and thus hides the polygon, no matter the order I put them in. This also stays true if I have the polygon start a frame later than the image.
e.g. see inn the code below (created with the Builder before compiling) how both a blue square and a red triangle are supposed to start at frame 0, but when you run it the blue square always covers the red triangle!?
Is there a way to have the polygon on top? Do I somehow need to merge the image and polygon before drawing them?
Thank you so much for your help!!
Sebastian
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
This experiment was created using PsychoPy2 Experiment Builder (v1.81.03), Sun Jan 18 20:44:26 2015
If you publish work using this script please cite the relevant PsychoPy publications
Peirce, JW (2007) PsychoPy - Psychophysics software in Python. Journal of Neuroscience Methods, 162(1-2), 8-13.
Peirce, JW (2009) Generating stimuli for neuroscience using PsychoPy. Frontiers in Neuroinformatics, 2:10. doi: 10.3389/neuro.11.010.2008
"""
from __future__ import division # so that 1/3=0.333 instead of 1/3=0
from psychopy import visual, core, data, event, logging, sound, gui
from psychopy.constants import * # things like STARTED, FINISHED
import numpy as np # whole numpy lib is available, prepend 'np.'
from numpy import sin, cos, tan, log, log10, pi, average, sqrt, std, deg2rad, rad2deg, linspace, asarray
from numpy.random import random, randint, normal, shuffle
import os # handy system and path functions
# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__))
os.chdir(_thisDir)
# Store info about the experiment session
expName = u'test_triangle_over_square' # from the Builder filename that created this script
expInfo = {'participant':'', 'session':'001'}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False: core.quit() # user pressed cancel
expInfo['date'] = data.getDateStr() # add a simple timestamp
expInfo['expName'] = expName
# Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
filename = _thisDir + os.sep + 'data/%s_%s_%s' %(expInfo['participant'], expName, expInfo['date'])
# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',
extraInfo=expInfo, runtimeInfo=None,
originPath=None,
savePickle=True, saveWideText=True,
dataFileName=filename)
#save a log file for detail verbose info
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
logging.console.setLevel(logging.WARNING) # this outputs to the screen, not a file
endExpNow = False # flag for 'escape' or other condition => quit the exp
# Start Code - component code to be run before the window creation
# Setup the Window
win = visual.Window(size=(1280, 800), fullscr=True, screen=0, allowGUI=False, allowStencil=False,
monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
blendMode='avg', useFBO=True,
)
# store frame rate of monitor if we can measure it successfully
expInfo['frameRate']=win.getActualFrameRate()
if expInfo['frameRate']!=None:
frameDur = 1.0/round(expInfo['frameRate'])
else:
frameDur = 1.0/60.0 # couldn't get a reliable measure so guess
# Initialize components for Routine "trial"
trialClock = core.Clock()
ISI = core.StaticPeriod(win=win, screenHz=expInfo['frameRate'], name='ISI')
square = visual.ImageStim(win=win, name='square',units='pix',
image=None, mask=None,
ori=0, pos=[0, 0], size=[200, 200],
color=u'blue', colorSpace='rgb', opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-1.0)
polygon = visual.ShapeStim(win=win, name='polygon',units='pix',
vertices = [[-[200, 300][0]/2.0,-[200, 300][1]/2.0], [+[200, 300][0]/2.0,-[200, 300][1]/2.0], [0,[200, 300][1]/2.0]],
ori=0, pos=[0, 0],
lineWidth=1, lineColor=[1,1,1], lineColorSpace='rgb',
fillColor=u'red', fillColorSpace='rgb',
opacity=1,interpolate=True)
# Create some handy timers
globalClock = core.Clock() # to track the time since experiment started
routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine
#------Prepare to start Routine "trial"-------
t = 0
trialClock.reset() # clock
frameN = -1
# update component parameters for each repeat
# keep track of which components have finished
trialComponents = []
trialComponents.append(ISI)
trialComponents.append(square)
trialComponents.append(polygon)
for thisComponent in trialComponents:
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
#-------Start Routine "trial"-------
continueRoutine = True
while continueRoutine:
# get current time
t = trialClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *square* updates
if frameN >= 0 and square.status == NOT_STARTED:
# keep track of start time/frame for later
square.tStart = t # underestimates by a little under one frame
square.frameNStart = frameN # exact frame index
square.setAutoDraw(True)
# *polygon* updates
if frameN >= 0 and polygon.status == NOT_STARTED:
# keep track of start time/frame for later
polygon.tStart = t # underestimates by a little under one frame
polygon.frameNStart = frameN # exact frame index
polygon.setAutoDraw(True)
# *ISI* period
if t >= 0.0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t # underestimates by a little under one frame
ISI.frameNStart = frameN # exact frame index
ISI.start(0.5)
elif ISI.status == STARTED: #one frame should pass before updating params and completing
ISI.complete() #finish the static period
# check if all components have finished
if not continueRoutine: # a component has requested a forced-end of Routine
routineTimer.reset() # if we abort early the non-slip timer needs reset
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in trialComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# check for quit (the Esc key)
if endExpNow or event.getKeys(keyList=["escape"]):
core.quit()
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
else: # this Routine was not non-slip safe so reset non-slip timer
routineTimer.reset()
#-------Ending Routine "trial"-------
for thisComponent in trialComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
win.close()
core.quit()
As per Jonas' comment above, PsychoPy uses a layering system in which subsequent stimuli are drawn on top of previous stimuli (as in his code examples).
In the graphical Builder environment, drawing order is represented by the vertical order of stimulus components: stimuli at the top are drawn first, and ones lower down are progressively layered upon them.
You can change the order of stimulus components by right-clicking on them and selecting "Move up", "move down", etc as required.
Sebastian, has, however, identified a bug here, in that the intended drawing order is not honoured between ImageStim and ShapeStim components. As a work-around, you might be able to replace your ShapeStim with a bitmap representation, displayed using an ImageStim. Multiple ImageStims should draw correctly (as do multiple ShapeStims). To get it to draw correctly on top of another image, be sure to save it as a .png file, which supports transparency. That way, only the actual shape will be drawn on top, as its background pixels can be set to be transparent and will not mask the the underlying image.
For a long-term solution, I've added your issue as a bug report to the PsychoPy GitHub project here:
https://github.com/psychopy/psychopy/issues/795
It turned out to be a bug in the Polygon component in Builder.
This is fixed in the upcoming release (1.82.00). The changes needed to make the fix can be seen at
https://github.com/psychopy/psychopy/commit/af1af9a7a85cee9b4ec8ad5e2ff1f03140bd1a36
which you can add to your own installation if you like.
cheers,
Jon

Resources